200 lines
4.6 KiB
Arduino
200 lines
4.6 KiB
Arduino
|
//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);
|
||
|
}
|