-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eq3device/eq3interface: #12
base: master
Are you sure you want to change the base?
Conversation
…rn parsing. add functions for schedules. fix getInfo to setDate, fix various '0' fill left issues. Add CC-RT-M-BLE. return {error:<error>} on error rather than nothing. enhanced ecoMode ('holiday mode') setting with temp & date options
just did a VERY quick test, and it the NR node seems to work :) |
I notice in the node that you are setting a global[config.eq3device] = device. sorry, for the essay, but just thinking about how to approach the next step. |
@btsimonh thanks for your contribution. unfortunately I have no eq3 device in hand at the moment. if you are sure the code will fully function I am more than happy to merge it. would be great to test it further and make sure everything is in place. If there are any changes to the api please update the readme file as well. |
ok, will do more testing. thankyou... |
@btsimonh is this ready to merge? |
hi @alikh31, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work!
It's really helpful that you added some documentation.
The comments are mostly small things and style related, I didn't find anything actually wrong =)
It's always a good idea to keep functions/methods small, and their scope to a specific task.
I could test your work so far if you would like, I mostly use the manual and boost functions and valvePosition, targetTemperature properties. And since I get new hardware this week, I would be able to test the pairing as well.
I have a bunch of these
lib/eq3interface.js
Outdated
break; | ||
|
||
case 2: | ||
switch(info[1] & 0xf){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each case block could simply invoke it's own function so you can get smaller functions with nicer names. Having a nice name you could even remove comments like // normal info
.
case 1:
return this->parsedSysinfo();
break;
case 2:
return $this->parsedNormalInfo();
break;
This becomes even more relevant when you have things like nested switch-case blocks (like a few lines below).
lib/eq3interface.js
Outdated
}; | ||
break; | ||
|
||
case 0x21: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unclear what the meaning of 0x21
is. A comment would be nice here.
return new Buffer(`11${temp}${dur}`, 'hex') | ||
const temp = ('0'+(2 * temperature).toString(16)).slice(-2); | ||
const dur = ('0'+(minDuration / 5).toString(16)).slice(-2); | ||
return new Buffer(`14${temp}${dur}`, 'hex') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change intentional? (the change from 11 to 14)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes :). seem to remember it was wrong...., some time agao now though.
lib/eq3interface.js
Outdated
const tempNight = (2 * night).toString(16) | ||
const tempDay = (2 * day).toString(16) | ||
const tempNight = ('0'+(2 * night).toString(16)).slice(-2); | ||
const tempDay = ('0'+(2 * day).toString(16)).slice(-2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm understanding '0'+(
... ).slice(-2)
correctly, this is supposed to be a "left-pad" function.
While it is a neat way to expand a number to two digits, it is not very readable.
It would be nicer to have a function for it, with a name describing what happens:
function expandNumberToTwoDigits(str) {
return ('0'+str).slice(-2)
}
But seeing that what we actually want to do ist: convert an integer < 256 (and >= 0) to a two-digit hex value.
function byteToHex(number) {
('0'+(number).toString(16)).slice(-2);
}
The call site would then look something like this:
const tempDay = byteToHex(2 * day);
lib/eq3interface.js
Outdated
@@ -16,55 +16,251 @@ module.exports = { | |||
notificationCharacteristic: 'd0e8434dcd290996af416c90f4e0eb2a', | |||
serviceUuid: '3e135142654f9090134aa6ff5bb77046', | |||
payload: { | |||
getInfo: () => new Buffer('03', 'hex'), | |||
getSysInfo: () => new Buffer('00', 'hex'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for the changing the payload / buffer value?
Won't this break compatibility with other devices?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:). i remember now. I wondered why all my valves dates were screwed. 03 is setdate, and if any command is sent without the correct payload, the device seems to use either the last payload for that command, or maybe even just the remainign bytes of the last payload! So using 03 was setting the date back to the last date set by the phone app..... 00 seems to be the right command to send without a payload to get the status.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, so to get the status response, you must set the time/date. See earlier mods in eq3Device to change the getInfo call on the device level to call setDatetime. getSysInfo is a NEW command which gets a serial number, etc. (unknown format).
lib/eq3interface.js
Outdated
// start firmware update | ||
return { | ||
firwareupdate:true, | ||
raw:info, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mixed indentation
lib/eq3interface.js
Outdated
break; | ||
} | ||
return { | ||
firwareupdate:true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mixed indentation
const minute = date.getMinutes().toString(16) | ||
const second = date.getSeconds().toString(16) | ||
return new Buffer(prefix + year + month + day + hour + minute + second, 'hex') | ||
var out = new Buffer(7); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mixed indentation
setDay: (day) => { | ||
var out = new Buffer(16); | ||
out[0] = 0x10; | ||
out[1] = day.day; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mixed indentation
@thomasnordquist - ready for re-review :). my development flow is here: Off topic, but I can highly recommend this thermometer for ease of BLE integration, unless you are concerned about data security... (info is sent in advertisment, so simple, and no connection required). |
I installed your branch and everything checks out so far. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more review and a potential "bug"
} | ||
|
||
// +-7 degrees |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't resist
// +-7 degrees | |
// temerature offset ranging from -7 to +7 degrees celsius |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree; expect in your pull request :)
|
||
// read any return, and convert to a javascript structure | ||
// main oare function, which then defers to fiunctions above as required. | ||
parseInfo: function(info) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice that you reduced this function to pattern-matching only! 👍
module.exports = { | ||
writeCharacteristic: '3fa4585ace4a3baddb4bb8df8179ea09', | ||
notificationCharacteristic: 'd0e8434dcd290996af416c90f4e0eb2a', | ||
serviceUuid: '3e135142654f9090134aa6ff5bb77046', | ||
payload: { | ||
getInfo: () => new Buffer('03', 'hex'), | ||
getSysInfo: () => new Buffer('00', 'hex'), // note change from 03 - 03 is set date, and was RESETTING date every call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment why something has changed, should, in my opinion, be the responsibility the commit message which introduced the change. Referring to something that is no longer part of the code serves no purpose.
It's perfectly fine not to have the comment here, I only marked the place in the review because I was not able to explain the change with my limited knowledge.
setDatetime
also documents the 0x03
code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, the comment serves no purpose if you did not know is was getInfo before.... pls remove in pull request :)
dst: (statusMask & status.dst) === status.dst, | ||
openWindow: (statusMask & status.openWindow) === status.openWindow, | ||
lowBattery: (statusMask & status.lowBattery) === status.lowBattery, | ||
valvePosition, | ||
targetTemperature, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to duplicatevalvePosition
and targetTemperature
?
node-red-contrib-eq3-bluetooth/lib/eq3interface.js
Lines 173 to 181 in e27dfe7
lowBattery: (statusMask & status.lowBattery) === status.lowBattery, | |
valvePosition, | |
targetTemperature, | |
ecoendtime: ecoendtime, | |
}, | |
valvePosition, | |
targetTemperature, | |
}; | |
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh.. just so as not to break someone else who was using the output; yet they were 'in the wrong place' in my thinking, so I wanted to move them gracefully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll see your point. Nothing wrong with changing things. Probably it was not wise to name the group status
since everything here can be considered status 🤨
I see no harm if it stays how it is.
EQ3BLE.prototype.getInfo = function() { | ||
return this.writeAndGetNotification(eq3interface.payload.getInfo()) | ||
.then(info => eq3interface.parseInfo(info)) | ||
return this.writeAndGetNotification(eq3interface.payload.setDatetime(new Date())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
breaks setDateTime(date)
?!
setting the date will overwritten everytime one tries to get the info.
Is this still true since you changed the getInfo buffer from 0x03
to 0x00
?
// this sets the date; else the date can get set to old data in the buffer!!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with the right date? not sure how else to trigger the status :). just copying the android app....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, let me get back to you. I had some very nice reverse-engineered documents from someone else somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, I believe the engineers made the decision to update the thermostats clock whenever a phone is connected. Mixing responsibilities of functions is not a very nice thing to do...
By the way, the documentation I mentioned: https://github.com/Heckie75/eQ-3-radiator-thermostat/blob/master/eq-3-radiator-thermostat-api.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice documentation. I'm sure we don't cover it all.
By the way, nice thermometer. Even if it had no bluetooth 😅 |
Can you narrow the problem down? Might be more helpful for the devs if they had something reproducible to toy with. Something like a minimal example without hardware requirements? |
I tried, but the noble device is a VERY complex thing. could not reproduce with a simpler (very deep) structure. As I state in the forum, it could be just that the first time it actually fails, and breaks from then on. But it's gonna kill me when I update all my main stuff; I think the avoidance strategy is best; I do some evil stuff with contexts at the moment, all trying to avoid large messages (see 'clone'). To that forum message, I got one reply; I don't think others abuse NR as I do....! |
Do you maybe have a cyclic reference?
|
yep, tested with that :). browser shows 'Circular', and is fine. it's just one to avoid; there is not value having a large structure in the displayed context; it's great for 'normal' people :). |
Do you have info on how to use https://github.com/btsimonh/node-red-contrib-eq3-bluetooth/blob/e27dfe72b1d3a1f851d8d05c96e3332f4466a522/lib/eq3interface.js#L36 ? I'm documenting the node and how to use it, but the description is rather confusing: |
no, didn't play with it too much; so much guessing. The docs you highlighted are quite good though..... |
lib/eq3interface.js
Outdated
@@ -11,60 +11,301 @@ const status = { | |||
lowBattery: 128, | |||
} | |||
|
|||
// convert any number to 2 digits hex. | |||
// ensures integer, and takes last two digits of hex conversion with zero filling to 2 if < 16 | |||
var h2 = function(val) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is broken
var h2 = function(val) { | |
var h2 = function(number) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hah, never trust an englishman! Had a suspicion that something was up with my rads; now I know - the time has probably been s****d for a month! (actually, date/time seems correct; but I've not run anything more complex than polling since the changes....)
Setting the temperature was no longer possible.
If you poll a lot, you might want to take a look at influxdb and grafana
und 😉
|
Hi @btsimonh and @thomasnordquist sorry I've been away for a while. again since I have no physical devices I can not actually test the code but it looks legit to me. if you guys are happy with it I can merge the pr and release the package. |
Hi @btsimonh , I am currently testing branch btsimonh/node-red-contrib-eq3-bluetooth#btsimonh There are some minor glitches (like "list of all available addressess will be retrieved..." never returning a list) which I want to report as issue on your repository. kr |
Hi Alikh31,
I've been working a lot with these devices now, and returned to noble (trying to make it work better!).
One of the things I've done is some heavy updates on the two lib files; in theory these mods don't change anything related to the node-red node, but I've NOT tested with the actual node. (all testing in function nodes so far).
If you are able to test in your setup, that would be great.
Details:
Make ALL sends parse the return.
Enhance return parsing.
add functions for schedules.
fix getInfo to setDate (it was screwing with my date/time on devices? - using the last time sent to it!).
fix various '0' fill left issues.
Add CC-RT-M-BLE.
return {error:} on error rather than nothing.
enhanced ecoMode ('holiday mode') setting with temp & date options.
I AM successfully using multiple devices with noble now.
So my next task is to review the node functionality with regard to what I want to achieve, and see if I can enhance it without disturbing existing users :). If I can, I'll provide another pull request.....