Create Hotdog script to interface between MQTT and the radio
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
arduino_secrets.h
|
||||||
185
HDPacketBuilder.h
Normal file
185
HDPacketBuilder.h
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
#include <CRC16.h>
|
||||||
|
|
||||||
|
#define LENGTH_17 (0x11)
|
||||||
|
#define LENGTH_21 (0x15)
|
||||||
|
#define LENGTH_25 (0x19)
|
||||||
|
|
||||||
|
#define VERSION_5 (0x05)
|
||||||
|
#define VERSION_6 (0x06)
|
||||||
|
|
||||||
|
uint8_t rollingCode1 = 0xAC;
|
||||||
|
uint8_t rollingCode2 = 0x82;
|
||||||
|
|
||||||
|
uint8_t buf[32];
|
||||||
|
|
||||||
|
CRC16 crc(0x755B, 0x0, 0xBA68, false, false);
|
||||||
|
|
||||||
|
void setPacketLength(uint8_t);
|
||||||
|
void setConstants();
|
||||||
|
void setSourceRemoteAddress();
|
||||||
|
void setHubSourceAddress();
|
||||||
|
void setRollingCodes();
|
||||||
|
void setProtocolVersion(uint8_t);
|
||||||
|
void calculateCRC();
|
||||||
|
|
||||||
|
|
||||||
|
void constructUpPacket()
|
||||||
|
{
|
||||||
|
setPacketLength(LENGTH_17);
|
||||||
|
setConstants();
|
||||||
|
setSourceRemoteAddress();
|
||||||
|
setRollingCodes();
|
||||||
|
setProtocolVersion(VERSION_6);
|
||||||
|
|
||||||
|
buf[11] = 0x04; // Shade ID (group 4 for now)
|
||||||
|
buf[12] = 0x00; // Shade ID
|
||||||
|
|
||||||
|
buf[16] = 0x55; // Command
|
||||||
|
buf[17] = 0x00; // Empty?
|
||||||
|
|
||||||
|
calculateCRC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void constructDownPacket()
|
||||||
|
{
|
||||||
|
setPacketLength(LENGTH_17);
|
||||||
|
setConstants();
|
||||||
|
setSourceRemoteAddress();
|
||||||
|
setRollingCodes();
|
||||||
|
setProtocolVersion(VERSION_6);
|
||||||
|
|
||||||
|
buf[11] = 0x04; // Shade ID (group 4 for now)
|
||||||
|
buf[12] = 0x00; // Shade ID
|
||||||
|
|
||||||
|
buf[16] = 0x44; // Command
|
||||||
|
buf[17] = 0x00; // Empty?
|
||||||
|
|
||||||
|
calculateCRC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void constructStopPacket()
|
||||||
|
{
|
||||||
|
setPacketLength(LENGTH_17);
|
||||||
|
setConstants();
|
||||||
|
setSourceRemoteAddress();
|
||||||
|
setRollingCodes();
|
||||||
|
setProtocolVersion(VERSION_6);
|
||||||
|
|
||||||
|
buf[11] = 0x04; // Shade ID (group 4 for now)
|
||||||
|
buf[12] = 0x00; // Shade ID
|
||||||
|
|
||||||
|
buf[16] = 0x53; // Command
|
||||||
|
buf[17] = 0x00; // Empty?
|
||||||
|
|
||||||
|
calculateCRC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void constructPositionPacket(float percentage)
|
||||||
|
{
|
||||||
|
setPacketLength(LENGTH_21);
|
||||||
|
setConstants();
|
||||||
|
setHubSourceAddress(); // TODO: Will this source address work?
|
||||||
|
setRollingCodes();
|
||||||
|
setProtocolVersion(VERSION_5);
|
||||||
|
|
||||||
|
buf[11] = 0x4E; // Shade ID?
|
||||||
|
buf[12] = 0xF1; // Shade ID?
|
||||||
|
|
||||||
|
buf[15] = 0x3F; // Command
|
||||||
|
buf[16] = 0x5A; // Empty?
|
||||||
|
|
||||||
|
buf[17] = 0x04; // Constant in this size packet?
|
||||||
|
buf[18] = 0x40; // Constant in this size packet?
|
||||||
|
buf[19] = 0x50; // Constant in this size packet?
|
||||||
|
|
||||||
|
uint16_t position = (uint16_t)(0xFFFF * percentage);
|
||||||
|
|
||||||
|
buf[20] = (uint8_t)(position & 0x00FF);
|
||||||
|
buf[21] = (uint8_t)((position & 0xFF00) >> 8);
|
||||||
|
|
||||||
|
calculateCRC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPacketLength(uint8_t length) {
|
||||||
|
buf[0] = length; // Packet size
|
||||||
|
}
|
||||||
|
|
||||||
|
void setConstants() {
|
||||||
|
buf[1] = 0x00; // Constant?
|
||||||
|
buf[2] = 0x05; // Constant?
|
||||||
|
|
||||||
|
buf[4] = 0xff; // Constant?
|
||||||
|
buf[5] = 0xff; // Constant?
|
||||||
|
|
||||||
|
buf[8] = 0x86; // Constant?
|
||||||
|
|
||||||
|
buf[15] = 0x52; // Constant?
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSourceRemoteAddress() {
|
||||||
|
buf[6] = 0x36; // Source address?
|
||||||
|
buf[7] = 0x9e; // Source address?
|
||||||
|
|
||||||
|
buf[13] = 0x36; // Source address again?
|
||||||
|
buf[14] = 0x9e; // Source address again?
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHubSourceAddress() {
|
||||||
|
buf[6] = 0x00; // Source address?
|
||||||
|
buf[7] = 0x00; // Source address?
|
||||||
|
|
||||||
|
buf[13] = 0x00; // Source address again?
|
||||||
|
buf[14] = 0x00; // Source address again?
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRollingCodes() {
|
||||||
|
buf[3] = rollingCode1; // Rolling code 1
|
||||||
|
buf[10] = rollingCode2; // Rolling code 2
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProtocolVersion(uint8_t version) {
|
||||||
|
buf[9] = version; // Protocol version?
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateCRC() { // must be called after the buffer has been filled
|
||||||
|
crc.restart();
|
||||||
|
uint8_t length = buf[0];
|
||||||
|
switch(length) {
|
||||||
|
case 0x11:
|
||||||
|
crc.setXorOut(0xBA68);
|
||||||
|
break;
|
||||||
|
case 0x15:
|
||||||
|
crc.setXorOut(0xE10C);
|
||||||
|
break;
|
||||||
|
case 0x19:
|
||||||
|
crc.setXorOut(0x89A0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Serial.print("Unsupported length (");
|
||||||
|
Serial.print(length);
|
||||||
|
Serial.println("). Cannot calculate CRC");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
crc.add(buf, length + 1);
|
||||||
|
uint16_t result = crc.calc();
|
||||||
|
uint8_t checksum1 = (uint8_t)((result & 0xFF00) >> 8);
|
||||||
|
uint8_t checksum2 = (uint8_t)(result & 0x00FF);
|
||||||
|
|
||||||
|
buf[length + 1] = checksum1; // Checksum
|
||||||
|
buf[length + 2] = checksum2; // Checksum
|
||||||
|
}
|
||||||
|
|
||||||
|
void printHex(uint8_t num) { //print a byte as two hex chars
|
||||||
|
char hexCar[3];
|
||||||
|
sprintf(hexCar, "%02X", num);
|
||||||
|
Serial.print(hexCar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBuffer() //print a byte array as hex chars
|
||||||
|
{
|
||||||
|
uint8_t bytecount = buf[0] + 3;
|
||||||
|
for (int i = 0; i < bytecount; i++) {
|
||||||
|
printHex(buf[i]);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
119
Hotdog.ino
Normal file
119
Hotdog.ino
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#include "arduino_secrets.h"
|
||||||
|
#include "HDPacketBuilder.h"
|
||||||
|
#include <EspMQTTClient.h>
|
||||||
|
#include <RF24.h> // library by TMRh20
|
||||||
|
|
||||||
|
#define SER_BAUDRATE (115200)
|
||||||
|
|
||||||
|
// pins for: esp8266 NodeMCU v3 dev board
|
||||||
|
#define RF_CE_PIN (5) // pins for: esp
|
||||||
|
#define RF_CS_PIN (15) // pins for: esp
|
||||||
|
#define RF_IRQ_PIN (4) // run a jumper from IRQ pin to pin 2
|
||||||
|
|
||||||
|
EspMQTTClient client(
|
||||||
|
SECRET_WIFI_SSID, // Wifi SSID
|
||||||
|
SECRET_WIFI_PASSWORD, // Wifi Password
|
||||||
|
SECRET_MQTT_SERVER_IP, // MQTT Broker server IP
|
||||||
|
SECRET_MQTT_USERNAME, // MQTT Username
|
||||||
|
SECRET_MQTT_PASSWORD, // MQTT Password
|
||||||
|
"hotdog", // MQTT Client ID
|
||||||
|
1883
|
||||||
|
);
|
||||||
|
|
||||||
|
byte addr[3] = { 0xC0, 0xC8, 0x2E }; // The address was captured as "2EC8C0" and the bytes were reversed
|
||||||
|
|
||||||
|
RF24 radio(RF_CE_PIN, RF_CS_PIN);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
buf[i] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.begin(SER_BAUDRATE);
|
||||||
|
|
||||||
|
client.setKeepAlive(10);
|
||||||
|
client.enableLastWillMessage("hotdog/availability", "offline", true);
|
||||||
|
client.enableDebuggingMessages();
|
||||||
|
|
||||||
|
radio.begin();
|
||||||
|
radioTransmitSetup();
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
buf[i] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("Ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
void onConnectionEstablished() {
|
||||||
|
|
||||||
|
client.subscribe("hotdog/test_mqtt_blind/set", [] (const String &payload) {
|
||||||
|
Serial.print("Set on test_mqtt_blind: ");
|
||||||
|
Serial.println(payload);
|
||||||
|
if (payload == "OPEN") {
|
||||||
|
constructUpPacket();
|
||||||
|
printBuffer();
|
||||||
|
sendCommand(buf);
|
||||||
|
} else if (payload == "CLOSE") {
|
||||||
|
constructDownPacket();
|
||||||
|
printBuffer();
|
||||||
|
sendCommand(buf);
|
||||||
|
} else if (payload == "STOP") {
|
||||||
|
constructStopPacket();
|
||||||
|
printBuffer();
|
||||||
|
sendCommand(buf);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.subscribe("hotdog/test_mqtt_blind/set_position", [] (const String &payload) {
|
||||||
|
Serial.print("Set position on test_mqtt_blind: ");
|
||||||
|
Serial.println(payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.publish("hotdog/availability", "online", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
client.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void radioTransmitSetup() {
|
||||||
|
radio.stopListening();
|
||||||
|
radio.powerDown();
|
||||||
|
radio.begin();
|
||||||
|
delay(100);
|
||||||
|
Serial.println();
|
||||||
|
radio.setChannel(0x07); //shooting for 2.407 GHz
|
||||||
|
radio.setDataRate(RF24_1MBPS); //can go at 250kbs, 1Mbs, 2Mbs
|
||||||
|
radio.setPALevel(RF24_PA_HIGH); //transmit power
|
||||||
|
radio.disableCRC();
|
||||||
|
radio.setAutoAck(false);
|
||||||
|
radio.setAddressWidth(3);
|
||||||
|
radio.setRetries(0, 0);
|
||||||
|
|
||||||
|
radio.openWritingPipe(addr);
|
||||||
|
radio.powerUp();
|
||||||
|
//radio.printDetails();
|
||||||
|
//radio.printPrettyDetails();
|
||||||
|
Serial.println("Ready to Transmit");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendCommand(byte * byteArray) //transmit a command
|
||||||
|
{
|
||||||
|
uint8_t bytecount = byteArray[0] + 3;
|
||||||
|
for (int j = 1; j < 5; j++) {
|
||||||
|
radio.setAddressWidth(3);
|
||||||
|
radio.disableCRC();
|
||||||
|
radio.setAutoAck(false);
|
||||||
|
radio.openWritingPipe(addr);
|
||||||
|
for (int i = 1; i < 200; i++) {
|
||||||
|
radio.writeFast(byteArray, bytecount);
|
||||||
|
}
|
||||||
|
delay(500);
|
||||||
|
radio.flush_tx();
|
||||||
|
radio.txStandBy();
|
||||||
|
}
|
||||||
|
|
||||||
|
rollingCode1++;
|
||||||
|
rollingCode2++;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user