lichtorgel/lichtorgel_mqtt/lichtorgel_mqtt.ino

200 lines
4.6 KiB
C++

//http://homieiot.github.io/homie-esp8266/docs/develop/configuration/json-configuration-file/
//curl -X PUT http://homie.config/config -d @config.json --header "Content-Type: application/json"
/*Example data/homie/config.json
{
"name": "geraet",
"device_id": "geraet",
"wifi": {
"ssid": "blafoo",
"password": "password"
},
"mqtt": {
"host": "mqttbrokerhostname",
"port": 1883,
"auth": false
},
"ota": {
"enabled": false
}
}
*/
//3M
#include <Homie.h>
#include <Adafruit_NeoPixel.h>
#include <ArduinoOTA.h>
HomieNode homieNode("lamp", "lamp"); //id, type
#define PIN_SR_DATA D5
#define PIN_SR_LTCH D6
#define PIN_SR_CLOCK D7
#define OUTPUTS 6
long lastTickMillis;
uint8_t out[OUTPUTS];
long lastChange=0;
#define STANDBYTIME 5000 //time in ms after lamps switch off if nothing happened
boolean standby=false;
#define MAXONTIME 1000 //maximum time in ms a lamp should be turned on (for lampoffmillis value)
long lampoffmillis[OUTPUTS]; //time (millis()) at which lamp should turn off
uint16_t last_data=0;
void setup()
{
pinMode(PIN_SR_DATA, OUTPUT);
pinMode(PIN_SR_LTCH, OUTPUT);
pinMode(PIN_SR_CLOCK, OUTPUT);
shiftRelais(0);
Serial.begin(115200);
Serial.println();
Homie_setFirmware("lichtorgel", "1.0.0");
Homie.setLoopFunction(loopHandler);
homieNode.advertiseRange("duration", 0, OUTPUTS - 1).settable(onSetLamp); // lichtorgel/lamp/duration_n/set
Homie.setup();
ArduinoOTA.setHostname("lichtorgel");
/*ArduinoOTA.onStart([]() {
});
ArduinoOTA.onEnd([]() {
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
strip.setPixelColor(progress / (total / NUMPIXELS), strip.Color(100, 0, 0));
strip.show();
});*/
ArduinoOTA.begin();
}
void loop()
{
Homie.loop();
ArduinoOTA.handle();
}
void loopHandler() {
long loopmillis=millis();
uint16_t data=0;
for (uint8_t i=0; i<OUTPUTS; i++){
if (lampoffmillis[i]>loopmillis){ //turn lamp on if offtime is above current time
data|=1<<i; //set bit
}
}
if (millis()-lastChange >=STANDBYTIME && !standby){
Serial.println("Standby");
data=0;
shiftRelais(0);
standby=true;
}
if (data!=last_data){ //output changed
shiftRelais(mapData(data));
printBinary(data);
lastChange=loopmillis;
last_data=data;
}
/*
int packetSize = Udp.parsePacket();
if (packetSize)
{
// receive incoming UDP packets
Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
int len = Udp.read(incomingPacket, 255);
if (len > 0)
{
incomingPacket[len] = 0;
}
uint16_t data=incomingPacket[0]<<8 | incomingPacket[1];
Serial.printf("UDP packet contents: %s\n", incomingPacket);
printBinary(data);
printBinary(mapData(data));
shiftRelais(mapData(data));
lastChange=millis();
standby=false;
}*/
}
void printBinary(uint16_t value){
for(int i = 15; i >=0; i--) {
Serial.print((value & (1 << ((byte)i) )) ? 1 : 0);
//Serial.print(!!(value & (1 << i))); //this should also work
}
Serial.println();
}
uint16_t mapData(uint16_t x){ //because shift register pinout is different from actual outlet connection numbering
uint16_t d=0;
d|=moveByte(x,0,1);
d|=moveByte(x,1,2);
d|=moveByte(x,2,3);
d|=moveByte(x,3,4);
d|=moveByte(x,4,5);
d|=moveByte(x,5,6);
d|=moveByte(x,6,7);
d|=moveByte(x,7,0);
return d;
}
uint16_t moveByte(uint16_t x,uint8_t from,uint8_t to){
//example: x=00110101 from=2 to=0 -> 00000001
return ((x&_BV(from))>0) ? _BV(to):0;
}
void shiftRelais(uint16_t data) {
digitalWrite(PIN_SR_LTCH, LOW);
shiftOut(PIN_SR_DATA, PIN_SR_CLOCK, MSBFIRST, (data >> 8));
shiftOut(PIN_SR_DATA, PIN_SR_CLOCK, MSBFIRST, data & 0xff);
digitalWrite(PIN_SR_LTCH, HIGH);
}
bool onSetLamp(const HomieRange& range, const String& value) { //lamp index (range) and on time (in ms)
standby=false;
lastChange=millis();
Serial.print("onSetLamp ");
Serial.print(range.index);
Serial.print(" value=");
Serial.println(value);
if (!range.isRange) {
//long set_offmillis=value.toInt());
//homieNode.setProperty("duration").send(value);
return false; //range must be specified
}
if (range.index < 0 || range.index >= OUTPUTS) { //out of range
return false;
}
long set_offmillis=value.toInt()+millis();
if (set_offmillis>millis()+MAXONTIME){
set_offmillis=millis()+MAXONTIME; //limit value
}
lampoffmillis[range.index]=set_offmillis;
Serial.print("lampoffmillis[");
Serial.print(range.index);
Serial.print("]=");
Serial.println(lampoffmillis[range.index]);
homieNode.setProperty("duration_" + String(range.index)).send(value);
}