-
Notifications
You must be signed in to change notification settings - Fork 130
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
Add Support for Insteon iMeter Solo and SynchroLinc #374
Conversation
Initial draft, I don't have either device, so I can't test much.
Thanks so much for this @krkeegan! I finally had a chance to poke at this today and wanted to share my findings. Initial testing shows the code can read the iMeter on initial startup:
Setting the device state to refresh yeilds:
which is likely related to when calling request_status() it doesn't seem to do anything. I also noticed that get_power() was missing. |
Oops, forgot that I need to add a special derive_state routine so that "refresh" will work. Shouldn't be a big deal. What do you mean "get_power" is missing. I assume you are trying to get the instantaneous usage? If so simply calling request_status, to get the value, and then retreiving the value from $miner_power3->state will do it. The state of the device should be the instantaneous power value. Also, is $miner_power3 a crypto-currency miner? Seems like a good way to figure out the returns on your electricity usage. |
No worries @krkeegan... My original code had a get_power() function which returned just the instantaneous power value ($$self{'power'}), and get_accumenergy() which returned the accumulated power usage ($$self{'accumenergy'}) and I noticed you had a corresponding get_accumulated_usage() function that does the same thing as get_accumenergy(), but the equivalent of get_power() seemed to be missing for functional parity. $miner_power3 is indeed a cryptocurrency miner and it's predecessor was the inspiration for me to develop the original iMeter support code. |
Brian, I added back in the get_power function. I also fixed up the code so that "refresh" should work. Let me know if that fixes things for you. |
Here is what I am seeing beginning with startup (with insteon debugging enabled this time):
The Reading iMeter (scheduled) log event indicates when some user code fires every minute and calls $miner_power3->request_status(). Requesting status or refreshing (from the web interface) also doesn't seem to have an effect (but there isn't an error this time) |
Here is another log extract with the debug level for insteon set all the way to 4:
It would appear that despite calling request_status() after the device is first initialized, no Insteon command is actually being sent. |
Hmm, odd. It is working, but it seems to be throwing an odd message back at us every now and then. First, this entry in the first log:
Is odd. When MH starts up, it sends a request_status command to each device. In this excerpt, it is sending the command to the iMeter. The iMeter responds with some unknown command, MH then tries again, and the iMeter responds in a way we understand. This produces the final status line. So request_status is working. To further compound the oddity, the second log seems to show that this unknown command is repeatable. MH starts up and goes through the same process and we get similar results, including the odd first response, but a legitimate response on the second attempt. From the extended log, we can see that the odd response back is:
We expect Cmd1 to be 0x82 not 0x88. The rest of the values in D1-D14 also don't quite work. The power level would be 289 watts, the accumulated energy would be 263,774.60/kWh. It looks like this message means something else. What I don't know, nor do I know why the iMeter seems to be responding with this message for the first response to request_status. Now, why isn't your code causing request_status to run? I don't know. Try running the voice command 'status' on the device and see what happens. That certainly works for me. Similarly, setting the state of the device to 'refresh' also causes request_status to run for me. I did fix one glitch last night which was preventing the state of the object from being set to the Power Value. |
This post seems to suggest that the iMeter sends out spurious 0x88 messages every now and then: http://forum.universal-devices.com/viewtopic.php?p=47621&sid=e4949f24fb08e8b95b1e4a053ff8db64#p47621 |
Thanks @krkeegan, The 0x88 message is indeed odd and unexpected. I was simply ignoring them in my original code, so I didn't even notice them until now. I have indeed set the state of the device to refresh, as well as invoking the status voice command to no avail. Here is an excerpt from my user code: $v_query_imeter = new Voice_Cmd 'Read iMeter';
$v_reset_imeter = new Voice_Cmd 'Reset iMeter accumulated usage';
$v_get_imeter_power = new Voice_Cmd 'Get iMeter power';
$v_get_imeter_accumulated_usage = new Voice_Cmd 'Get iMeter accumulated usage';
if ($state = said $v_query_imeter) {
print_log "Reading iMeter";
$miner_power3->request_status();
}
if ($state = said $v_reset_imeter) {
print_log "Resetting iMeter accumulated energy";
$miner_power3->reset_accumulated_usage();
}
# Poll for changes every 1 minute
if (new_minute 1) {
print_log "Reading iMeter (scheduled)";
$miner_power3->request_status();
}
if ($state = said $v_get_imeter_power) {
print_log "Power is " . $miner_power3->get_power() . "W";
respond $miner_power3->get_power() . "W";
}
if ($state = said $v_get_imeter_accumulated_usage) {
print_log "Accumulated energy is " . $miner_power3->get_accumulated_usage() . "kWh";
respond $miner_power3->get_accumulated_usage() . "kWh";
} I added an additional debug statement to request_status() to see if it was actually getting called, and it does appear to be, but nothing is actually getting sent after the first imeter_query goes out. sub request_status
{
my ($self,$requestor) = @_;
my $extra = '00';
::print_log("[Insteon::iMeter] sending imeter_query for " . $self->get_object_name) if $self->debuglevel(1, 'insteon');
my $message = new Insteon::InsteonMessage('insteon_send', $self, 'imeter_query', $extra);
$self->_send_cmd($message);
return;
}
|
Hmm, maybe the current message is never getting cleared. |
I was thinking the same thing, but haven't yet wrapped my head around how everything with the new Insteon code works to find out why. |
OK, I think that my last commit should solve it. Sorry about all the testing, not having a device really makes coding more difficult. |
Thanks @krkeegan, that seems to have done it! I had to make a minor change to my user code to properly trigger off the state change, but all appears to be working now. From if (state_now $miner_power3 eq 'power_change') { To if ($state = state_now $miner_power3) { FYI: I also verified that reset_accumulated_usage() is working as expected. |
I ran a few longer tests today as I was merging in my old user code into a new MH install and after running for 20-30 minutes I stopped getting iMeter updates. I'm not sure if this is due to those spurious 0x88 messages, but wanted to report it here. I'll try to do more testing over the weekend with the log level cranked up to see if it helps expose what is happening. |
I ran another test overnight starting Friday night into Saturday, and eventually the issue re-occurred. I stopped the test only a few minutes after noticing it, but hopefully there is enough here to be helpful:
|
So what happens to the rest of MH after this happens? At 11:25:00, MH sends the iMeter request. However, the PLM doesn't acknowledge receiving anything. MH retries 5 times, and the PLM never responds in any way. This is not normal, in fact I have never seen this. The PLM should always respond to receiving data, in the worst case, the PLM will balk at the command with a What happens if you try and send other commands once this state has been reached? Does the PLM ever wake back up again? Do you have some sort of exotic connection to your PLM? |
Hi @krkeegan, Unfortunately I terminated MH after the last log line shown in my post. The web interface was responsive before I terminated MH, and otherwise it seemed to be working properly. I didn't have any other Insteon devices on the powerline during the test apart from the iMeter, but will do so during the next test run. As far as an exotic connection to the PLM goes no. I have the PLM on a USB 2.0 hub on the USB 2.0 port on my CentOS 6.4 box. Other USB devices connected via this hub were working properly w/o interruption during this time. |
Yes, MH itself should continue to operate normally. I am curious to know if the PLM would respond to a different command? Or a different device? PLM lockups did happen in the past. For the most part, I think we overcame them 6-8 months ago by being more careful with our message handling. To my knowledge, when they did happen, they looked a lot like what you are seeing. I don't see anything in particular that would cause a lockup to occur. Sending a status_request every minute creates more traffic than normal, but it shouldn't be an issue. I have a script that sends a status_request to a different device that rotates every minute. This is similar and hasn't cause me any issued. However, I do wonder whether the PLM has some sort of "de-deuplication" inside of it that is causing it to ignore repeated messages in some manner. |
I captured logs from another test run and was able to get it to fail again, but this time it appears to have done so differently than last time. For some reason this time request_status() stops sending messages to the PLM as though the message wasn't being removed from the command stack. This may be related to the all_link_clean_status that happens at 12:47.
After noticing the issue, I sent power on and off commands to $water_pump1 which works as expected. It did not 'reset' whatever issue was happening with reading the imeter. |
Wow, @rudybrian it looks like you found a bug in a very low level routine in the Insteon stack. From a quick glance, it appears that the portion of the code that parses out messages received from the PLM has incorrectly parsed a message from inside another message. The Extended Received Msg should be 84 characters long. Only a portion of that message arrives during this loop (not uncommon for these long extended messages). The code recognizes that this is not a complete message. But then it bizarrely tries to process the message and finds a short 025801 message buried inside (the all link cleanup). Processing this causes all sorts of problems. The solution is to fix the parser. This is a bit scary though, the parser is not written how I would choose to do it and the logic is not always clear to me. I would feel much more comfortable just rewriting it, but this will take time. I will look later and see if I can figure out a quick solution to your issue. I suspect the 025801 characters are always present in the status responses from your iMeter. As a result, if an extended message is not fully delivered in a single loop (which is not uncommon) this will likely happen again. Still doesn't explain the prior problem and may not explain all of your problems. Since you keep finding nifty things, I selfishly wouldn't mind if you kept testing things out. |
Glad this was helpful @krkeegan! I'll happily keep testing and will report what I find. |
FYI: I ran three separate test runs today and after varying amounts of time all eventually resulted in the same parsing of the incomplete extended message as was observed yesterday. |
I ran another batch of tests which all but one ultimately resulted in the parsing of the incomplete extended message and subsequent ignoring of requested updates as was seen before. The one exception occurred when I started a test (by restarting MH) just before the end of the minute, causing my user code to fire at the start of a new minute while the Insteon devices were still syncing with the PLM/MH. This also resulted in MH ignoring requests that should have been sent to the iMeter:
|
Changes the PLM parser to a First-In-First-Out style. This should resolve the issue found in hollie#374 where shorter messages were being excerpted out of the middle of larger messages. I believe the routine is significantly easier to read. Removed the use of the split routine which created really odd results, and was not the most logical code to follow. This also likely solves other latent issues that may not have been apparent.
The code in this pull request seems to be working. I am going to merge this and submit a new pull request to try and resolve the parser errors that @rudybrian is getting. |
Add Support for Insteon iMeter Solo and SynchroLinc
I coded this without having the devices on hand, so I can't be sure it works. I was only able to test to make sure that the MH code was stable.
I added support for everything I know about these devices, but there may be features that I was not able to discover from my web searches.
If anyone has one of these, I would be interested to know how this works. Both devices are very different from the normal Insteon type devices.
Fixes #372