I have spent about 2 days getting this to work so I thought others would benefit if I document a working setup.
There is information out there - but I found it incompete. Some of what I include below is obvious, some is obscure and hard to find.
What I had to work with
- Homeassistant: Standard clean install. Refered to as
HAbelow. - Dragino LPS8v2 as LoRaWAN Network Server & Chirpstack as the Application Server.
- Dragino LHT52 Temp/Humidity sensor. Manual
Starting Point
See: this
Objective
Run a script on HA that sends a command to the LHT52
The mechanism is:
- Use
HAscripts to send an MQTT message to the MQTT server built into LPS8v2/Chirpstack - This MQTT message is received by the
encodeDownlink()codec function, and Chirpstack adds the message to the downlink queue for the end device.
Hints/Tricks
- The MQTT message can include ONE of these options:
- a Base64-encoded command, that bypasses the
encodeDownlink()function and just gets added to the downlink queue, or - a JSON object that can contain anything. The
encodeDownlink()function must create the downlink command from that JSON. Importantly, there is no Base64 involved at all using this method.
- a Base64-encoded command, that bypasses the
HA(as I write this) can do Base64 encoding of ASCII strings, but not binary byte arrays. As the commands are binary byte arrays, the JSON object method has to be used.HAcan only subscribe to ONE MQTT server. While there is an MQTT server built into Chirpstack, chances areHAwill be connected to a different MQTT server (often the MQTT server installed on theHAserver) to gather data from more than just LoRaWAN sensors. See below the discussion on MQTT Servers.
MQTT Servers
In my setup, the primary MQTT server was the one bundled with HA ( = [HA-MQTT]).
Uplink sensor data messages flow like this:
[LPS8V2][MQTT Forwarder] --->[HA-MQTT]->[HA]
Downlink command messages flow like this:
[HA]->[HA-MQTT]---bridge--->[Chirpstack MQTT][Chirpstack]
To get this to work, it is neccessary to use MQTT Bridging to get [HA-MQTT] to be a client of [Chirpstack MQTT]
These are the clearest instructions I could find.
Here is my /share/mosquitto/lwgateway.conf file.
connection LwGateway
address dragino-2a748c.local
topic # out # HA-MQTT forwards on all messages to LwGateway
HA scripts
My design was to have:
- Separate
command scripts; one for each downlink command.- e.g.
Alarmcommand - e.g.
Resetcommand
- e.g.
- A common
SendCommandscript that sends the command to[Chirpstack MQTT]
The pseudo-code is:
SetTempAlarm(applicationID, devEui, enable, minutes, templowc, temphighc)
Build command;
SendCommand(applicationID, devEui,command);
Build Topic & payload
mqtt.publish(Topic, payload)
SetTempAlarm script
sequence:
- variables:
basecommand: AA
enablecommand: "00"
- if:
- condition: template
value_template: "{{ enable }}"
then:
- variables:
enablecommand: "01"
- action: script.sendcommand
metadata: {}
data:
devEui: "{{ devEui }}"
applicationID: "{{ applicationID }}"
command: >-
{{ basecommand ~ enablecommand ~ '%04X'%minutes ~ '%04X'%templowc ~
'%04X'%temphighc }}
fields:
devEui:
selector:
text: null
name: devEui
description: DevEUI
required: true
enable:
selector:
boolean: {}
name: enable
required: true
default: true
templowc:
selector:
number:
min: -100
max: 200
name: TempLowC
description: Alarm lower temp
default: 21
required: true
temphighc:
selector:
number:
min: -100
max: 200
name: TempHighC
description: Alarm upper temp
default: 32
required: true
minutes:
selector:
number:
min: 1
max: 100
name: minutes
description: interval to check temp
required: true
default: 2
applicationID:
selector:
text: null
name: applicationID
description: Chirpstack Application ID
required: true
alias: SetTempAlarm
description: Sets the Alarm for Dragino LHT devices
SendCommand Script
sequence:
- action: mqtt.publish
metadata: {}
data:
qos: "0"
retain: false
topic: application/{{ applicationID }}/device/{{ devEui }}/command/down
payload: >-
{ "devEui":"{{ devEui }}","confirmed": false,"fPort":
1,"object":{"command":"{{command}}"} }
fields:
devEui:
selector:
text: null
name: devEui
description: DevEUI
required: true
applicationID:
selector:
text: null
name: applicationID
description: Chirpstack Application ID
required: true
command:
selector:
text: {}
name: Command
description: Hex String
required: true
alias: SendCommand
description: Sends MQTT message to the Gateway with a downlink command
Chirpstack Encoder
This is appended to:
- Chirpstack > Tenant > Device Profiles > [device] > Codec >Payload codec
- Chirpstack > Network Server > Device Profile Templates > [device] > Codec > Payload codec
function encodeDownlink(input) {
var command = input.data.command;
var output = [];
for (var i=0,j=0; i<command.length; i+=2,j++) {
output[j]=parseInt(command.substr(i,2), 16);
}
return {bytes: output};
}
Hope this helps the next person