nutechsoftware / alarmdecoder

Python interface for the Alarm Decoder (AD2) family of alarm devices. (AD2USB, AD2SERIAL and AD2PI)
MIT License
63 stars 40 forks source link

AD2PI firmware failure - attempting to recover #70

Open Nu11u5 opened 1 year ago

Nu11u5 commented 1 year ago

I noticed this issue back in January and tried to contact Nu Tech for support by email and forums but never got a response or account activated. There is no GitHub project for the AD2PI firmware/hardware, and this seems like the next best location.


Background:

This issue started following a power supply problem with the RPi. The RPi would not boot and made a "hissing" sound. After replacing the USB power supply with a new one and rebuilding the SD card (using the AlarmDecoder image) it booted and there were no unusual sounds.

Issue:

In the AlarmDecoder webapp, the AD2PI was failing setup tests. The webapp prompted "firmware update available", but the update page now displayed the firmware version as "unknown". Attempting to update the FW from the webapp would not complete.

After this I shelled in and tried using ad2-firmwareupload with both localhost:10000 and /dev/serial0 (with ser2sock, nginx, and gunicorn stopped). Both methods only output:

Flashing device: localhost:10000 - 115200 baud
Firmware: ./ademcoemu_V2-2a-8-8.hex

..but nothing else and were still running after 30 minutes.

I also tried using screen to open /dev/serial0. Initially, if I pressed "!" the console would output "!no", "!wait", and a lot of garbage characters. On one attempt this test also output "!lboot" and "!load" but has not been reproducible using screen. The latest attempts using screen will output nothing.

Since then I have also tried using tcpdump to capture ser2sock communication to localhost:10000. In most cases ad2-firmwareupload will open the connection and ser2sock will return a few single-byte payloads and then stop communication (connection is still open). In one case, ser2sock eventually returned "!wait" followed by "!load", then ad2-firmwareupload sent several packets of ASCII data in the form of:

:10000 0000F724 70E23CA3 C4D82C4E E148E43C E8C31
:10000 80039DAA B5279A08 A5D82C4E E148E43C E8C65
:10001 000816CC 9FB056D5 FE26A8EC F0316196 61D00
:10002 00032008 A3DAF0BC 3742F809 946F86CE 50A05
:10003 0000AB18 47DB0743 A53D60F8 25B85CB1 C61C4
...

The reply from ser2sock after every packet in this sequence was always:

!0000 :0000

After 11 such data packets ser2sock stopped replying and ad2-firmwareupload stopped sending. This was the only attempt that even got this far. I can share the .PCAP file if needed (note: if I still have it from 10 months ago).

Request:

My question is what is happening here? Is my AD2PI recoverable, and if so what procedure is involved?

f34rdotcom commented 1 year ago

The "!boot" message is a problem. Depending on what version of AD2pHat board you have this is a little harder to fix. The AD2pHat board has lost its firmware and is now in a mode expecting new firmware.

It should be possible to update the firmware using the WEBUI or using the firmware upload tool in the AlarmDecoder Python api folder under the '''bin''' folder look for a script called ad2-firmwareupload

If ser2sock is used then make sure nothing else is talking to ser2sock including the webapp by stopping gunicorn.

./ad2-firmwareupload ademcoemu_V2-2a-8-9b-306.hex localhost:10000

If it works then when you connect to the ser2sock using telnet and send the command 'V' to the AD2pHat board it should spit out its version correctly and the !boot...load messages will have stopped.

Best SM

Nu11u5 commented 1 year ago

@f34rdotcom - I have the original AD2PI board, not the redesigned AD2pHAT. I'm not sure of the differences other than the board layout and the GPIO header.

As described in the post in detail, I've already tried writing new firmware using the ad2-firmwareupload command. What I see is that ser2sock just stops responding after a few packets/blocks, and the firmware tool just idles waiting for the response.

f34rdotcom commented 1 year ago

What if you disable ser2sock and go directly to /dev/ttyS0 or what ever it is on your pi that ser2sock was connecting to. If you can connect to the device directly then report back the data. If it is in !boot load mode then it should be no problem flashing it with the utility. The newer version does have its RESET line tied to GPIO 18. Sometimes it is necessary to reboot the AD2* device and force it into boot loader mode if the existing firmware is corrupt. It sounds like your device is just waiting for a full flash and something is interrupting the process.

Nu11u5 commented 1 year ago

I'll give that a try.

Is there a reference for the serial protocol used by the AD2PI? How do I read the status?

f34rdotcom commented 1 year ago

You can read my wiki if it is up. I am doing a lot of network refactoring these past few weeks so no promises. https://www.alarmdecoder.com/wiki/index.php/Protocol

Just parsing section 1 from all messages on a single partition system is easy. Read a message and look if it is a state message then look at the fixed byte position for the BITFIELD being tracked such as FIRE. Just note that the FIRE bit when triggered by the alarm can return to '0' even if the fire is still active. This is one of the quirks the C++ api deals with using timers etc. Most bits like the ALARM bit are simple and will be a '1' if the alarm bell is sounding and a '0' if the alarm bell is off.

A good starting point for advanced decoding is my recent work on the C++ parser. https://github.com/nutechsoftware/AlarmDecoder-IoT/blob/master/components/alarmdecoder-api/alarmdecoder_api.cpp

This parser splits messages by partition for multiple partition systems and tracks event states such as zone changes better than the current Python API.

// Construct parser object
AlarmDecoderParser AD2Parse;

// Create a partition state to monitor events from.
// For DSC use partition # for Ademco use keypad assigned to the partition.
AD2PartitionState *s = AD2Parse.getAD2PState(18, true);

// Optional: Save the AD2 address.
s->primary_address = 18;

// Optional: Add zones to zone_list. Not required user defined.
s->zone_list.push_front(2);
s->zone_list.push_front(3);
s->zone_list.push_front(4);

// Optional: Set user defined zone string that can be used later. Not required.
AD2Parse.setZoneString(252, '{"type": "problem", "alpha": "Failed to call(FC)"}');

// Subscribe to events passing in user defined arg in this case the event ID being called.
AD2Parse.subscribeTo(ON_FIRE_CHANGE, _fire_callback_function, (void *)ON_FIRE_CHANGE);

// Receive data from the AD2* uart and send it to the AlarmDecoderParser
loop() {
 AD2Parse::put((int8*)ad2protocolstreamptr, (int8)buffer_length);
}

// callback example
void _fire_callback_function(std::string *msg, AD2PartitionState *s, void *arg)
{
   printf("FIRE event message: '%s'\r\n", s->last_event_message.c_str());
}
Nu11u5 commented 1 year ago

@f34rdotcom So I was able to reinstall the firmware, and the solution should have been more obvious. Turns out the replacement power supply was under-spec at 1A and I didn't notice until now that the power LED on the RPi was flickering - the voltage was stable enough for the RPi but not the AD2PI. I replaced it with a 2A supply and the AD2PI accepted the firmware update via web console.

Kind of a testament to the high build quality of the AD2PI, since it was unaffected by weeks of unstable voltages :)

Thanks for the support and ongoing development of AlarmDecoder!


A separate question - what is the status of connectivity with the SmartThings platform?

I understand that the existing SmartApp is deprecated with the imminent removal of the Groovy API. I also believe I understand that the AD2-IoT project was created to make use of the new SDK available for Arduino devices, which would integrate with SmartThings via the cloud. Has use of the new SmartThings Edge Drivers (Lua script) been considered to allow direct communication between a SmartThings Hub and AlarmDecoder/webapp? If I wanted to integrate with SmartThings once the Groovy API is gone what are the options?