diff --git a/HCPBridgeCombo/Arduino/.gitignore b/HCPBridgeCombo/Arduino/.gitignore new file mode 100644 index 0000000..d3e0c0c --- /dev/null +++ b/HCPBridgeCombo/Arduino/.gitignore @@ -0,0 +1,5 @@ +/.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/HCPBridgeCombo/Arduino/.vscode/extensions.json b/HCPBridgeCombo/Arduino/.vscode/extensions.json new file mode 100644 index 0000000..e80666b --- /dev/null +++ b/HCPBridgeCombo/Arduino/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/HCPBridgeCombo/Arduino/include/README b/HCPBridgeCombo/Arduino/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/HCPBridgeCombo/Arduino/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/HCPBridgeCombo/Arduino/lib/README b/HCPBridgeCombo/Arduino/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/HCPBridgeCombo/Arduino/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/HCPBridgeCombo/Arduino/platformio.ini b/HCPBridgeCombo/Arduino/platformio.ini new file mode 100644 index 0000000..0c67b85 --- /dev/null +++ b/HCPBridgeCombo/Arduino/platformio.ini @@ -0,0 +1,20 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:pro8MHzatmega328] +platform = atmelavr +board = pro8MHzatmega328 +; change microcontroller +board_build.mcu = atmega328p +; change MCU frequency +board_build.f_cpu = 8000000L + +framework = arduino +lib_deps = \ No newline at end of file diff --git a/HCPBridgeCombo/Arduino/src/hciemulator.cpp b/HCPBridgeCombo/Arduino/src/hciemulator.cpp new file mode 100644 index 0000000..885b05c --- /dev/null +++ b/HCPBridgeCombo/Arduino/src/hciemulator.cpp @@ -0,0 +1,415 @@ +#include "hciemulator.h" +#define CHECKCHANGEDSET(Target,Value,Flag) if((Target)!=(Value)){Target=Value;Flag=true;} +int hciloglevel = DEFAULTLOGLEVEL; + +#ifdef SOFTSERIAL +#define Log(Level,Message) LogCore(Level,Message) +#define Log3(Level,Message,Buffer, Len) LogCore(Level,Message,Buffer,Len) +//LOGLEVEL +void LogCore(int Level, const char* msg, const unsigned char * data=NULL, size_t datalen=0){ + if(Level>hciloglevel){ + return; + } + if(data!=NULL && datalen>0){ + String newmsg(msg); + char str[4]; + for (size_t i = 0; i < datalen; i++){ + snprintf(str,sizeof(str),"%02x ", data[i]); + newmsg+=str; + } + Serial.println(newmsg); + }else{ + Serial.println(msg); + } +} +#else + #define Log(Level,Message) + #define Log3(Level,Message,Buffer, Len) +#endif + + +int HCIEmulator::getLogLevel(){ + return hciloglevel; + +} +void HCIEmulator::setLogLevel(int level){ + hciloglevel=level; +} + +//modbus crc calculation borrowed from: +//https://github.com/yaacov/ArduinoModbusSlave +#define MODBUS_CRC_LENGTH 2 +#define readCRC(arr, length) word(arr[(length - MODBUS_CRC_LENGTH) + 1], arr[length - MODBUS_CRC_LENGTH]) +#define readUInt16(arr, index) word(arr[index], arr[index + 1]) +/** + * Calculate the CRC of the passed byte array from zero up to the passed length. + * + * @param buffer The byte array containing the data. + * @param length The length of the byte array. + * + * @return The calculated CRC as an unsigned 16 bit integer. + * + * Calculate and add the CRC. + * uint16_t crc = Modbus::calculateCRC(_responseBuffer, _responseBufferLength - MODBUS_CRC_LENGTH); + * _responseBuffer[_responseBufferLength - MODBUS_CRC_LENGTH] = crc & 0xFF; + * _responseBuffer[(_responseBufferLength - MODBUS_CRC_LENGTH) + 1] = crc >> 8; + * + * + * #define MODBUS_FRAME_SIZE 4 + * #define MODBUS_CRC_LENGTH 2 + * uint16_t crc = readCRC(_requestBuffer, _requestBufferLength); + * #define readUInt16(arr, index) word(arr[index], arr[index + 1]) + * #define readCRC(arr, length) word(arr[(length - MODBUS_CRC_LENGTH) + 1], arr[length - MODBUS_CRC_LENGTH]) + */ +uint16_t calculateCRC(uint8_t *buffer, int length) +{ + int i, j; + uint16_t crc = 0xFFFF; + uint16_t tmp; + + // Calculate the CRC. + for (i = 0; i < length; i++) + { + crc = crc ^ buffer[i]; + for (j = 0; j < 8; j++) + { + tmp = crc & 0x0001; + crc = crc >> 1; + if (tmp) + { + crc = crc ^ 0xA001; + } + } + } + return crc; +} + +HCIEmulator::HCIEmulator(Stream * port) { + m_state.valid = false; + m_statemachine=WAITING; + m_rxlen = m_txlen = 0; + m_recvTime=m_lastStateTime=0; + m_skipFrame=false; + m_port = port; + setLogLevel(DEFAULTLOGLEVEL); +}; + +void HCIEmulator::poll(){ + + if(m_port==NULL) return; + + // receive Data + if(m_port->available() >0) + { + m_rxlen+= m_port->readBytes((char*)(m_rxbuffer+m_rxlen), min((int)(255-m_rxlen),m_port->available())); + if(m_rxlen > 254) + { + Log(LL_ERROR,"RX Bufferoverflow, skip next Frame"); + Log3(LL_DEBUG,"Buffer Data: ", m_rxbuffer, m_rxlen); + m_rxlen=0; + m_skipFrame = true; + } + m_recvTime = micros(); + } + + + // check frame, process frame + if(m_rxlen>0 && (micros()-m_recvTime > T3_5)) + { + // check last action timeout -> reset > then 2sec + if(m_statemachine!= WAITING && m_lastStateTime+2000 0){ + + // fix crc + uint16_t crc = calculateCRC(m_txbuffer, m_txlen - MODBUS_CRC_LENGTH); + m_txbuffer[m_txlen - MODBUS_CRC_LENGTH] = crc & 0xFF; + m_txbuffer[(m_txlen - MODBUS_CRC_LENGTH) + 1] = crc >> 8; + + // send data + m_lastSendTime = micros()-m_recvTime; + + //Log(LL_DEBUG, ("ST:"+String(m_lastSendTime)).c_str()); + + m_port->write(m_txbuffer, m_txlen); + Log3(LL_DEBUG,"Response: ", m_txbuffer, m_txlen); + m_txlen = 0; + } + } + + m_skipFrame = false; + m_rxlen=0; + } +} + +void HCIEmulator::processFrame(){ + m_txlen = 0; // clear send buffer + + if(m_rxlen<5) { + Log(LL_ERROR,"Frame skipped, invalid frame len"); + Log3(LL_ERROR,"Data:", m_rxbuffer,m_rxlen); + return; + } + + // check device id, pass only device id 2 and 0 (broadcast) + if(m_rxbuffer[0] != BROADCASTID && m_rxbuffer[0] != DEVICEID){ + Log(LL_DEBUG,"Frame skipped, unsupported device id"); + Log3(LL_DEBUG,"Data:", m_rxbuffer,m_rxlen); + return; + } + + // check crc + uint16_t crc = readCRC(m_rxbuffer, m_rxlen); + if(crc != calculateCRC(m_rxbuffer,m_rxlen-MODBUS_CRC_LENGTH)){ + Log3(LL_ERROR,"Frame skipped, wrong crc", m_rxbuffer,m_rxlen); + return; + } + + Log3(LL_DEBUG,"Incomming Data: ", m_rxbuffer, m_rxlen); + + // dispatch modbus function + switch(m_rxbuffer[1]){ + case 0x10:{ // Write Multiple registers + if(m_rxlen == 0x1b && m_rxbuffer[0] == BROADCASTID) + { + processBroadcastStatusFrame(); + return; + } + break; + } + + case 0x17:{ // Read/Write Multiple registers + if(m_rxbuffer[0] == DEVICEID){ + switch(m_rxlen){ + case 0x11:{ + processDeviceStatusFrame(); + return; + } + + case 0x13: + processDeviceBusScanFrame(); + return;; + } + } + break; + } + } + Log3(LL_ERROR,"Frame skipped, unexpected data: ", m_rxbuffer, m_rxlen); +} + +const unsigned char ResponseTemplate_Fcn17_Cmd03_L08 []= {0x02,0x17,0x10,0x3E,0x00,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x1B}; +const unsigned char ResponseTemplate_Fcn17_Cmd04_L02 []= {0x02,0x17,0x04,0x0F,0x00,0x04,0xFD,0x0A,0x72}; +void HCIEmulator::processDeviceStatusFrame(){ + if(m_rxlen==0x11){ + unsigned char counter = m_rxbuffer[11]; + unsigned char cmd = m_rxbuffer[12]; + if(m_rxbuffer[5] == 0x08){ + // expose internal state + // 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 + //0011: 02 17 9C B9 00 08 9C 41 00 02 04 3E 03 00 00 EB CC + //res=> 02 17 10 3E 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 74 1B + memcpy(m_txbuffer, ResponseTemplate_Fcn17_Cmd03_L08, sizeof(ResponseTemplate_Fcn17_Cmd03_L08)); + m_txbuffer[0] = m_rxbuffer[0]; + m_txbuffer[3] = counter; + m_txbuffer[5] = cmd; + m_txlen = sizeof(ResponseTemplate_Fcn17_Cmd03_L08); + + + switch(m_statemachine) + { + // open Door + case STARTOPENDOOR: + m_txbuffer[7]= 0x02; + m_txbuffer[8]= 0x10; + m_statemachine = STARTOPENDOOR_RELEASE; + m_lastStateTime = millis(); + break; + case STARTOPENDOOR_RELEASE: + if(m_lastStateTime+SIMULATEKEYPRESSDELAYMS 02 17 04 0F 00 04 FD 0A 72 + memcpy(m_txbuffer, ResponseTemplate_Fcn17_Cmd04_L02, sizeof(ResponseTemplate_Fcn17_Cmd04_L02)); + m_txbuffer[0] = m_rxbuffer[0]; + m_txbuffer[3] = counter; + m_txbuffer[5] = cmd; + m_txlen = sizeof(ResponseTemplate_Fcn17_Cmd04_L02); + return; + } + } + + Log3(LL_ERROR,"Frame skipped, unexpected data: ", m_rxbuffer, m_rxlen); +} + +const unsigned char ResponseTemplate_Fcn17_Cmd02_L05 []= {0x02,0x17,0x0a,0x00,0x00,0x02,0x05,0x04,0x30,0x10,0xff,0xa8,0x45,0x0e,0xdf}; +void HCIEmulator::processDeviceBusScanFrame(){ + // 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 + //0013: 02 17 9C B9 00 05 9C 41 00 03 06 00 02 00 00 01 02 f8 35 + //res=> 02 17 0a 00 00 02 05 04 30 10 ff a8 45 0e df + unsigned char counter = m_rxbuffer[11]; + unsigned char cmd = m_rxbuffer[12]; + memcpy(m_txbuffer, ResponseTemplate_Fcn17_Cmd02_L05, sizeof(ResponseTemplate_Fcn17_Cmd02_L05)); + m_txbuffer[0] = m_rxbuffer[0]; + m_txbuffer[3] = counter; + m_txbuffer[5] = cmd; + m_txlen = sizeof(ResponseTemplate_Fcn17_Cmd02_L05); + + Log(LL_INFO,"Busscan received"); +} + +void HCIEmulator::processBroadcastStatusFrame(){ + //001B: 00 10 9D 31 00 09 12 64 00 00 00 40 60 00 00 00 00 00 00 00 00 00 01 00 00 CA 22 + bool hasChanged = false; + CHECKCHANGEDSET(m_state.lampOn,m_rxbuffer[20] == 0x14,hasChanged); + CHECKCHANGEDSET(m_state.doorCurrentPosition,m_rxbuffer[10],hasChanged); + CHECKCHANGEDSET(m_state.doorTargetPosition, m_rxbuffer[9],hasChanged); + CHECKCHANGEDSET(m_state.doorState, m_rxbuffer[11],hasChanged); + CHECKCHANGEDSET(m_state.reserved, m_rxbuffer[17],hasChanged); + CHECKCHANGEDSET(m_state.valid, true,hasChanged); + m_state.cc = m_rxbuffer[7]; + +} + +void HCIEmulator::openDoor(){ + if(m_statemachine != WAITING){ + return; + } + m_lastStateTime = millis(); + m_statemachine = STARTOPENDOOR; +} + +void HCIEmulator::openDoorHalf(){ + if(m_statemachine != WAITING){ + return; + } + m_lastStateTime = millis(); + m_statemachine = STARTOPENDOORHALF; +} + +void HCIEmulator::closeDoor(){ + if(m_statemachine != WAITING){ + return; + } + m_lastStateTime = millis(); + m_statemachine = STARTCLOSEDOOR; +} + +void HCIEmulator::stopDoor(){ + if(m_statemachine != WAITING){ + return; + } + m_lastStateTime = millis(); + m_statemachine = STARTSTOPDOOR; +} + +void HCIEmulator::toggleLamp(){ + if(m_statemachine != WAITING){ + return; + } + m_lastStateTime = millis(); + m_statemachine = STARTTOGGLELAMP; +} + +void HCIEmulator::ventilationPosition(){ + if(m_statemachine != WAITING){ + return; + } + m_lastStateTime = millis(); + m_statemachine = STARTVENTPOSITION; +} diff --git a/HCPBridgeCombo/Arduino/src/hciemulator.h b/HCPBridgeCombo/Arduino/src/hciemulator.h new file mode 100644 index 0000000..c037c77 --- /dev/null +++ b/HCPBridgeCombo/Arduino/src/hciemulator.h @@ -0,0 +1,117 @@ +#ifndef __hciemulator_h +#define __hciemulator_h + +#include +#include +#include "i2cshare.h" + +#define LL_OFF 0 +#define LL_ERROR 1 +#define LL_WARN 2 +#define LL_INFO 3 +#define LL_DEBUG 4 + +#define DEFAULTLOGLEVEL LL_WARN + +#define DEVICEID 0x02 +#define BROADCASTID 0x00 +#define SIMULATEKEYPRESSDELAYMS 100 + + +// Modbus states that a baud rate higher than 19200 must use a fixed 750 us +// for inter character time out and 1.75 ms for a frame delay. +// For baud rates below 19200 the timeing is more critical and has to be calculated. +// E.g. 9600 baud in a 10 bit packet is 960 characters per second +// In milliseconds this will be 960characters per 1000ms. So for 1 character +// 1000ms/960characters is 1.04167ms per character and finaly modbus states an +// intercharacter must be 1.5T or 1.5 times longer than a normal character and thus +// 1.5T = 1.04167ms * 1.5 = 1.5625ms. A frame delay is 3.5T. +#define T1_5 750 +#define T3_5 4800 //1750 + + +enum DoorState : uint8_t { + DOOR_OPEN_POSITION = 0x20, + DOOR_CLOSE_POSITION = 0x40, + DOOR_HALF_POSITION = 0x80, + DOOR_MOVE_CLOSEPOSITION = 0x02, + DOOR_MOVE_OPENPOSITION = 0x01, + +}; + +enum StateMachine: uint8_t{ + WAITING, + + STARTOPENDOOR, + STARTOPENDOOR_RELEASE, + + STARTOPENDOORHALF, + STARTOPENDOORHALF_RELEASE, + + STARTCLOSEDOOR, + STARTCLOSEDOOR_RELEASE, + + STARTSTOPDOOR, + STARTSTOPDOOR_RELEASE, + + STARTTOGGLELAMP, + STARTTOGGLELAMP_RELEASE, + + STARTVENTPOSITION, + STARTVENTPOSITION_RELEASE +}; + +class HCIEmulator { +public: + HCIEmulator(Stream * port); + + void poll(); + + void openDoor(); + void openDoorHalf(); + void closeDoor(); + void stopDoor(); + void toggleLamp(); + void ventilationPosition(); + + const SHCIState& getState() { + if(micros()-m_recvTime > 2000000){ + // 2 sec without statusmessage + m_state.valid = false; + } + return m_state; + }; + + unsigned long getMessageAge(){ + return micros()-m_recvTime; + } + + int getLogLevel(); + void setLogLevel(int level); + +protected: + void processFrame(); + void processDeviceStatusFrame(); + void processDeviceBusScanFrame(); + void processBroadcastStatusFrame(); + +private: + Stream *m_port; + SHCIState m_state; + StateMachine m_statemachine; + + unsigned long m_recvTime; + unsigned long m_lastStateTime; + unsigned long m_lastSendTime; + + size_t m_rxlen; + size_t m_txlen; + + unsigned char m_rxbuffer[255]; + unsigned char m_txbuffer[255]; + + bool m_skipFrame; +}; + + +#endif \ No newline at end of file diff --git a/HCPBridgeCombo/Arduino/src/i2cshare.h b/HCPBridgeCombo/Arduino/src/i2cshare.h new file mode 100644 index 0000000..e2bf980 --- /dev/null +++ b/HCPBridgeCombo/Arduino/src/i2cshare.h @@ -0,0 +1,26 @@ +#ifndef __i2cshare_h +#define __i2cshare_h + +#include + +#define I2CADDR 7 + +#define I2C_CMD_CLOSEDOOR 0 +#define I2C_CMD_OPENDOOR 1 +#define I2C_CMD_OPENDOORHALF 4 +#define I2C_CMD_STOPDOOR 2 +#define I2C_CMD_VENTPOS 3 +#define I2C_CMD_TOGGLELAMP 5 + +struct SHCIState{ + bool valid : 1; + bool lampOn : 1; + uint8_t doorState; // see DoorState + uint8_t doorCurrentPosition; + uint8_t doorTargetPosition; + uint8_t reserved; + uint8_t cc; +}; + + +#endif //__i2cshare_h \ No newline at end of file diff --git a/HCPBridgeCombo/Arduino/src/main.cpp b/HCPBridgeCombo/Arduino/src/main.cpp new file mode 100644 index 0000000..dca8f19 --- /dev/null +++ b/HCPBridgeCombo/Arduino/src/main.cpp @@ -0,0 +1,61 @@ +#include +#include +#include "hciemulator.h" +#include "i2cshare.h" + +#define RS485 Serial + +// Hörmann HCP2 based on modbus rtu @57.6kB 8E1 +HCIEmulator emulator(&RS485); + + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() { + Wire.write((unsigned char*)&(emulator.getState()), sizeof(SHCIState)); +} + +// function that executes whenever data is available by master +// this function is registered as an event, see setup() +void receiveEvent(int numBytes) { + while (Wire.available()){ + switch(Wire.read()){ + case I2C_CMD_CLOSEDOOR: + emulator.closeDoor(); + break; + case I2C_CMD_OPENDOOR: + emulator.openDoor(); + break; + case I2C_CMD_OPENDOORHALF: + emulator.openDoorHalf(); + break; + case I2C_CMD_STOPDOOR: + emulator.stopDoor(); + break; + case I2C_CMD_VENTPOS: + emulator.ventilationPosition(); + break; + case I2C_CMD_TOGGLELAMP: + emulator.toggleLamp(); + break; + } + } +} + + +// setup mcu +void setup(){ + + //setup modbus + RS485.begin(57600,SERIAL_8E1); + + //setup I2C + Wire.begin(I2CADDR); + Wire.onRequest(requestEvent); + Wire.onReceive(receiveEvent); +} + +// mainloop +void loop(){ + emulator.poll(); +} \ No newline at end of file diff --git a/HCPBridgeCombo/Arduino/test/README b/HCPBridgeCombo/Arduino/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/HCPBridgeCombo/Arduino/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/HCPBridgeCombo/ESP/.gitignore b/HCPBridgeCombo/ESP/.gitignore new file mode 100644 index 0000000..d3e0c0c --- /dev/null +++ b/HCPBridgeCombo/ESP/.gitignore @@ -0,0 +1,5 @@ +/.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/HCPBridgeCombo/ESP/.vscode/extensions.json b/HCPBridgeCombo/ESP/.vscode/extensions.json new file mode 100644 index 0000000..e80666b --- /dev/null +++ b/HCPBridgeCombo/ESP/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/HCPBridgeCombo/ESP/include/README b/HCPBridgeCombo/ESP/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/HCPBridgeCombo/ESP/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/HCPBridgeCombo/ESP/lib/README b/HCPBridgeCombo/ESP/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/HCPBridgeCombo/ESP/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/HCPBridgeCombo/ESP/platformio.ini b/HCPBridgeCombo/ESP/platformio.ini new file mode 100644 index 0000000..6934332 --- /dev/null +++ b/HCPBridgeCombo/ESP/platformio.ini @@ -0,0 +1,19 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp12e] +platform = espressif8266 +board = esp12e +framework = arduino +lib_deps = + ottowinter/ESPAsyncWebServer-esphome@^1.2.7 + bblanchon/ArduinoJson@^6.17.2 + ayushsharma82/AsyncElegantOTA@^2.2.5 + krzychb/EspSaveCrash@^1.2.0 \ No newline at end of file diff --git a/HCPBridgeCombo/ESP/src/index_html.h b/HCPBridgeCombo/ESP/src/index_html.h new file mode 100644 index 0000000..bb80e1c --- /dev/null +++ b/HCPBridgeCombo/ESP/src/index_html.h @@ -0,0 +1 @@ +const uint8_t index_html[] PROGMEM = {0x78,0xDA,0xA5,0x57,0xFD,0x6E,0xE3,0x36,0x12,0xFF,0x7B,0xFD,0x14,0xAC,0x0E,0x08,0xA4,0x8D,0xED,0x48,0xB2,0xB3,0xEB,0x5A,0x96,0x8B,0xED,0x66,0xAF,0xDB,0x62,0x7B,0x2D,0x9A,0x5C,0xD1,0x5E,0xB1,0x7F,0xD0,0xD4,0xC8,0x26,0x42,0x7D,0x1C,0x45,0xC5,0xF6,0x1A,0x7E,0x96,0xBE,0xC5,0xBD,0x40,0x5F,0xEC,0x86,0xA4,0x64,0xCB,0x89,0xB3,0x2D,0xD0,0xC0,0x8A,0x48,0xCE,0xCC,0x6F,0x3E,0x38,0x33,0xA4,0x66,0x5F,0xDC,0xFC,0xF0,0xF6,0xEE,0xD7,0x1F,0xDF,0x91,0xF7,0x77,0xDF,0x7F,0x98,0xCF,0x56,0x2A,0x13,0xF8,0x1F,0x68,0x32,0x9F,0x29,0xAE,0x04,0xCC,0xBF,0xA1,0x92,0x2E,0x21,0x57,0x85,0x24,0xB7,0x0A,0x6A,0x90,0x75,0xBE,0x9C,0x5D,0x59,0xDA,0x2C,0x03,0x45,0x49,0x4E,0x33,0x88,0x1F,0x38,0xAC,0xCB,0x42,0x2A,0xC2,0x8A,0x5C,0x21,0x7B,0xEC,0xAC,0x79,0xA2,0x56,0x71,0x02,0x0F,0x9C,0xC1,0xC0,0x4C,0xFA,0x84,0xE7,0x5C,0x71,0x2A,0x06,0x15,0xA3,0x02,0xE2,0xC0,0x69,0x10,0xD8,0x8A,0xCA,0x0A,0x54,0xFC,0xEF,0xBB,0x7F,0x0E,0x26,0xF3,0x99,0xE0,0xF9,0x3D,0x91,0x20,0x62,0x8E,0x60,0x64,0x25,0x21,0x8D,0x13,0xAA,0xE8,0xB4,0x3F,0x9F,0x55,0x6A,0x8B,0x7A,0x7B,0x04,0xFF,0xB4,0xA9,0x64,0x97,0xA2,0xBA,0x41,0x4A,0x33,0x2E,0xB6,0x53,0xF2,0x46,0x22,0x78,0x44,0x12,0x5E,0x95,0x82,0xE2,0x9C,0xE7,0x08,0x05,0x83,0x85,0x28,0xD8,0x7D,0x44,0x14,0x6C,0xD4,0x80,0x0A,0xBE,0xCC,0xA7,0x84,0xA1,0x89,0x20,0xA3,0xBD,0x45,0x0A,0x1B,0x9C,0x8A,0x7F,0x82,0x29,0x19,0x0D,0x7D,0x09,0x59,0x43,0x2B,0x9F,0x27,0x2D,0x8A,0x64,0x4B,0x76,0x19,0xDD,0x58,0xEF,0xA6,0xE4,0x95,0xEF,0x97,0x9B,0x88,0x64,0x54,0x2E,0x79,0x3E,0xC5,0x31,0xA1,0xB5,0x2A,0x22,0x52,0xD2,0x24,0xE1,0xF9,0x72,0xB0,0x28,0x94,0x2A,0xB2,0x29,0x09,0xAF,0x91,0xCD,0x62,0x0C,0xAB,0x35,0x57,0x6C,0x45,0x76,0x65,0x51,0x61,0x68,0x0A,0x34,0x0D,0x1D,0xA7,0x8A,0x3F,0xC0,0xB3,0x7E,0x34,0xDA,0x26,0x46,0xD9,0x0A,0xF8,0x72,0xA5,0xA6,0x64,0x3C,0x29,0x37,0x7B,0x72,0x82,0xC9,0xF3,0xB2,0x56,0x64,0x77,0x40,0xC9,0x8B,0x1C,0x5A,0xAD,0x82,0x27,0x20,0xBB,0x5A,0xE9,0xA2,0x2A,0x44,0xAD,0x50,0xAB,0x2A,0xCA,0x29,0xF1,0x23,0x22,0x20,0x55,0x66,0x20,0xAD,0x06,0x1C,0xB5,0x0E,0xE8,0x21,0x65,0xF7,0x4B,0x59,0xD4,0x79,0x32,0x60,0x85,0x28,0xE4,0x94,0xFC,0x83,0x31,0xA6,0x59,0x24,0x22,0x0F,0x24,0x4D,0x78,0x5D,0x61,0x48,0xD0,0xAA,0xAE,0xCA,0xE9,0x02,0xD2,0x42,0xC2,0x79,0xCD,0x4D,0xEA,0x4C,0x89,0xE3,0x1C,0x1D,0x1B,0x85,0xDA,0xCD,0xC6,0x67,0x3B,0xB1,0x96,0x4D,0xF4,0xB0,0xB5,0xC8,0x4E,0x9E,0xDA,0x94,0xA6,0x69,0x44,0x06,0x6B,0x58,0xDC,0x73,0x35,0x50,0x92,0xE6,0xAD,0xD6,0xE1,0xB8,0x42,0x57,0x1F,0x2F,0x3C,0xB2,0x7E,0xD4,0x5A,0x6F,0x42,0x39,0x65,0x2B,0x60,0xF7,0x90,0x5C,0x1E,0xC2,0x77,0x46,0xE1,0x62,0xE4,0xE3,0xDF,0x67,0xA4,0x0E,0x11,0x38,0xB1,0x0A,0x97,0xD0,0x0B,0x33,0xC4,0xDD,0x87,0x5F,0x5C,0xED,0xA9,0x87,0xA6,0x67,0xD5,0xE7,0x19,0x3E,0x43,0xDC,0xF7,0x5E,0xF4,0x5E,0x0C,0x17,0x35,0x46,0x28,0x27,0xBB,0xDE,0x8B,0x17,0xD6,0x3B,0xCC,0x15,0x0C,0xD6,0x61,0x3A,0x30,0x25,0x35,0x25,0xB8,0x09,0x3C,0xD1,0xCB,0x8D,0x27,0x0B,0x81,0xCE,0xE9,0x79,0x13,0xFA,0xC0,0x24,0x37,0xCE,0xDB,0x8D,0x39,0x2C,0x9C,0xA9,0x2B,0x5C,0x7D,0x94,0xBC,0x07,0xC6,0x04,0x58,0x21,0xA9,0x8D,0xB9,0xCE,0xC8,0x33,0xBC,0x4D,0xA2,0x23,0xC1,0x94,0xDE,0xBA,0x51,0xB8,0x28,0x44,0x72,0x58,0xB4,0xF5,0x18,0x36,0x26,0x34,0x25,0xA7,0x3D,0x23,0xA1,0x5D,0x62,0xB5,0xAC,0xB4,0x1F,0x65,0xC1,0x5B,0x93,0x1E,0xED,0xEE,0xB5,0x15,0xDE,0x1F,0x82,0x24,0x21,0xC1,0x3D,0xB5,0x4C,0xED,0x7E,0xBE,0xBB,0xB9,0xFE,0xF2,0x55,0x10,0x1D,0x99,0xB6,0x20,0x44,0xB1,0x7E,0xC2,0x97,0x32,0x46,0x7D,0xBF,0xC3,0xB7,0x94,0x00,0xF9,0x13,0xB6,0xF1,0x64,0x91,0x4C,0x10,0x8E,0xE8,0x52,0x9D,0x5D,0xD9,0x76,0x36,0xBB,0xB2,0x0D,0x57,0x37,0x14,0x6C,0xBE,0x61,0xA7,0xE7,0x22,0x29,0x9C,0xCF,0x18,0xCD,0x1F,0x68,0x65,0x8B,0x20,0x0E,0xB5,0xDD,0x4D,0x79,0x34,0x13,0x9E,0xC4,0x09,0x43,0x18,0xCB,0x87,0x10,0x23,0xBD,0x54,0x29,0xAA,0xEA,0x6A,0xBE,0xA6,0x52,0x01,0x76,0xA2,0x94,0xFC,0x0C,0x72,0xC1,0xF3,0x04,0x1B,0xF8,0x10,0x71,0x47,0xC8,0x27,0x51,0xA9,0xCD,0x0F,0x26,0x68,0x55,0xC5,0x4E,0x33,0x3B,0xC4,0xC3,0x21,0x45,0xCE,0x04,0x67,0xF7,0x71,0x52,0xBC,0x2D,0xB2,0x8C,0xE6,0x89,0x1B,0x78,0xF3,0x37,0x75,0x3A,0xBB,0xB2,0x4C,0x9F,0x45,0xB0,0xC1,0x3A,0x07,0x12,0x7A,0xF3,0x5B,0xEC,0x34,0x7F,0x09,0xC5,0x84,0xF2,0x1C,0x88,0xEF,0xCD,0xFF,0x53,0x1F,0x21,0xB4,0x3B,0xAB,0xF1,0xFC,0x03,0x67,0x2B,0x85,0x0E,0x8E,0xF1,0x24,0xA1,0x0B,0x10,0x0D,0xA6,0xED,0x8A,0xF3,0x99,0x6D,0x8B,0x6A,0x5B,0x42,0x6C,0x4A,0x73,0x51,0x6C,0x34,0xF4,0x8A,0xE6,0x4B,0xE8,0x60,0x5F,0x7B,0x3A,0x86,0x42,0x47,0x19,0x8F,0x9D,0x92,0xB6,0xA6,0xD9,0x2A,0xC6,0x60,0xEB,0x35,0x7C,0x19,0x15,0x56,0x77,0xC5,0x24,0x2F,0xD5,0x3C,0x29,0x0A,0x89,0xED,0x2D,0x0E,0xFC,0x28,0xE1,0x32,0x1E,0x04,0x11,0xAF,0xB0,0xB5,0xE5,0xC0,0x14,0x24,0x71,0x4A,0x45,0x05,0xD1,0x03,0x95,0x84,0xE6,0x3C,0x33,0x85,0x10,0xA5,0x75,0xCE,0xF4,0x80,0xE0,0x96,0x49,0x75,0x83,0xF2,0x6F,0x5A,0x9A,0xEB,0xED,0x78,0xEA,0x7E,0x71,0xE0,0xF5,0x76,0x87,0x61,0x8C,0x47,0xE6,0xB7,0x3A,0xB7,0x1F,0xA8,0x70,0x6F,0x24,0x5D,0xF7,0x43,0xDF,0xF7,0xA2,0xFD,0xBE,0xD7,0xC1,0x2B,0xCA,0x33,0x70,0x1D,0x34,0x26,0x80,0xCA,0x03,0xCA,0x91,0x80,0x99,0x7C,0x54,0x94,0xD7,0x42,0x44,0x1D,0x58,0xAD,0x0C,0x91,0xB4,0x13,0xD5,0xC3,0x12,0x83,0xC6,0xEA,0x0C,0xD3,0x75,0xB8,0x04,0xF5,0x4E,0x80,0x1E,0x7E,0xBD,0xFD,0x36,0x71,0x1D,0x24,0x3A,0x9E,0xF1,0x35,0x61,0xCF,0x73,0x25,0xAC,0x61,0x62,0x6A,0x83,0x79,0xAC,0xE9,0x6F,0xF5,0x49,0xB0,0x51,0xAE,0x13,0x26,0x48,0x6B,0x6E,0x12,0x6C,0x68,0x06,0x51,0x93,0xFA,0x38,0xB7,0xA3,0x08,0xE5,0x86,0xC6,0x8F,0x9F,0x30,0xC4,0xAE,0xDF,0xF7,0xFB,0xF6,0xBA,0x61,0xC9,0x5E,0xB4,0xA1,0xF1,0x6F,0xC1,0xA4,0xAF,0x7F,0x7E,0x7F,0xD4,0x0F,0x5E,0x8F,0xFB,0xA3,0xF1,0x6B,0x7C,0x70,0x36,0x0A,0xCD,0x13,0x7E,0xF9,0xDA,0x3C,0xD7,0xA1,0xFE,0x05,0x93,0x8F,0xD1,0x16,0x85,0x46,0xE1,0xEB,0x7E,0x10,0x8C,0xF1,0xC1,0xB7,0xEF,0xF7,0xC3,0xD0,0xBC,0xCC,0x14,0x97,0x35,0xD9,0xB2,0x84,0xE6,0x69,0xE6,0x1F,0x8D,0x41,0x29,0x17,0xE2,0x56,0x97,0x37,0x26,0xB3,0x6E,0xA5,0x8E,0x59,0x5D,0x00,0xF6,0xA9,0x1F,0xA9,0x5A,0xB9,0x5E,0x84,0x5D,0xDB,0xE5,0xB1,0x1F,0xF1,0xD9,0x86,0x0E,0x05,0xE4,0x4B,0xF4,0x8D,0x5F,0x5E,0x9A,0x1D,0xE2,0x71,0xEC,0xE3,0xE6,0xA0,0x44,0x56,0x3C,0xC0,0x5D,0xE1,0xBA,0x1B,0xFA,0x1B,0xFF,0x78,0x35,0xBA,0xF6,0xBD,0x97,0xD6,0x3B,0x77,0xFB,0x68,0x05,0xF7,0x0C,0x30,0xB7,0x8C,0x94,0x6E,0xA3,0x7F,0x59,0x6A,0xDF,0x6B,0x0D,0x3E,0xB1,0xAA,0xC9,0x63,0x6B,0x53,0xCB,0x61,0x42,0xEC,0xBE,0x0A,0x4F,0x30,0xDD,0x20,0xF4,0x2F,0xC3,0xE0,0x25,0xF7,0x4E,0x96,0xC3,0xF0,0xFA,0x64,0x1E,0x4C,0x4E,0xF5,0xF6,0x1A,0x0D,0x97,0x31,0xD6,0x49,0x84,0x5E,0xE3,0x6B,0xE6,0x5F,0x5C,0x34,0xCB,0x33,0x1D,0x02,0x5D,0x41,0xF8,0xBC,0x1C,0xE8,0x1E,0x6C,0x59,0xE6,0x47,0x96,0x39,0x16,0xD9,0x29,0x4F,0x27,0x4B,0x8F,0xB5,0x4C,0x99,0x4D,0x76,0x5D,0x49,0x9D,0x5A,0xF4,0x76,0x12,0x54,0x2D,0x73,0x44,0xD6,0xE9,0xB7,0x59,0xC9,0x38,0x87,0x35,0xF9,0xE5,0xFB,0x0F,0xEF,0x95,0x2A,0x7F,0x82,0xFF,0xD6,0x50,0x29,0x0C,0x09,0x12,0x86,0x45,0x09,0xB9,0xEB,0x7C,0xF3,0xEE,0xCE,0xE9,0x3B,0x57,0xCC,0xE2,0x7E,0x65,0x71,0x63,0xE7,0xD2,0x0E,0xFA,0x4A,0xD6,0x60,0xD9,0x2B,0x40,0xB5,0x5E,0xB7,0x66,0xB0,0x58,0x75,0x25,0xDE,0x62,0x53,0x06,0x57,0xB7,0x66,0xF0,0x76,0x67,0xCA,0x53,0x87,0xC1,0x50,0x4D,0x02,0x3C,0x69,0x25,0xFB,0x0E,0x3D,0x38,0xD2,0x2D,0xF9,0x84,0x1A,0x1E,0xA9,0xD7,0x2D,0xD5,0xD6,0x6D,0x87,0x69,0xE4,0x9D,0xEB,0x38,0x5D,0xB3,0xB1,0x18,0x6F,0xCD,0x39,0x72,0xA7,0xEB,0x91,0x9B,0x98,0x55,0xB5,0xC0,0xFB,0xFD,0x0D,0x9E,0x48,0x77,0xF8,0x55,0xE0,0xF4,0x6C,0x67,0xD5,0xC4,0xDE,0x8E,0xD1,0x0A,0x88,0xBF,0x09,0xFD,0xE9,0x89,0xC3,0x81,0x17,0xD9,0x58,0x13,0x2B,0x7E,0xE9,0xF0,0x4A,0x21,0xF8,0x1F,0xFF,0x4B,0xD3,0x1C,0xD4,0x10,0xAB,0xC3,0x0A,0x8E,0x1F,0x09,0xFA,0xCF,0x08,0x56,0x6C,0x25,0x8A,0x0A,0xC3,0x7C,0x14,0x9D,0x3C,0x12,0x0D,0xCF,0x8A,0x2A,0xE0,0xE2,0x8C,0x5E,0xFF,0x6F,0x09,0x87,0xA7,0xC2,0xA3,0x27,0xC2,0xDA,0x5C,0x0E,0x7F,0xFC,0xDE,0x15,0x0A,0xFE,0x4C,0xE8,0x54,0xCF,0x20,0x78,0x26,0x32,0xCE,0x3D,0x60,0xB5,0x77,0x4E,0x77,0xF2,0xA9,0xCE,0xF4,0xD6,0xA0,0x60,0x02,0x29,0x45,0xAC,0x69,0xC3,0x59,0xE7,0x0B,0xB8,0xA7,0xBA,0xDB,0x13,0xBB,0xAB,0x78,0xD7,0xBE,0xC4,0x6B,0x5F,0xB7,0x6C,0xEA,0x12,0x3F,0xB6,0xE0,0x06,0x3F,0xB8,0x9A,0x16,0xBF,0xC9,0xC4,0x0A,0xEB,0xE1,0x99,0xDA,0xB0,0xC4,0xA1,0xBE,0x2D,0xD0,0x64,0x6B,0xF2,0xAA,0x39,0x4B,0x5B,0x44,0x7B,0xE6,0xA8,0x15,0xAF,0x86,0x86,0xE7,0xD6,0xE6,0xDE,0xF8,0xE2,0xC2,0xAC,0xD9,0x6B,0x0A,0x26,0x2C,0x1E,0x5E,0xF6,0x48,0xB1,0x0B,0xDF,0xDD,0xFE,0xF0,0xAF,0x61,0xA9,0x3F,0x0C,0x5B,0xD9,0xAA,0x2C,0xF2,0x0A,0x74,0x22,0x7A,0x27,0x47,0xAA,0x15,0x18,0xE2,0x01,0x86,0xAE,0x3C,0x7F,0x18,0x19,0x2E,0xC7,0x1B,0x72,0x94,0x93,0xFA,0x73,0x37,0x3E,0x4D,0xEE,0x2E,0xCC,0x57,0xCD,0x44,0x97,0x90,0xF1,0x69,0x3A,0xC0,0x14,0x7E,0x16,0xDB,0x5C,0x13,0x10,0xBA,0xB9,0xEB,0xB7,0x16,0x09,0x9A,0x95,0x17,0x27,0xD6,0x1D,0x1A,0xCE,0xD3,0x2B,0xC1,0xFE,0x18,0xCB,0x6E,0xAF,0x69,0xCC,0x6E,0x7B,0x4B,0xC3,0x72,0xE8,0x2F,0x4D,0x49,0x77,0x37,0x2D,0xEA,0xDE,0x0B,0x8E,0x84,0xBE,0xFE,0x32,0xF1,0x22,0xBC,0xB8,0xD8,0x6B,0x0A,0xDE,0x9B,0xCC,0x7D,0xF3,0xCA,0x7C,0xF3,0xFF,0x1F,0xA6,0x8A,0x84,0xF0}; \ No newline at end of file diff --git a/HCPBridgeCombo/ESP/src/main.cpp b/HCPBridgeCombo/ESP/src/main.cpp new file mode 100644 index 0000000..270c877 --- /dev/null +++ b/HCPBridgeCombo/ESP/src/main.cpp @@ -0,0 +1,180 @@ +#include +#include "EspSaveCrash.h" +#include +#include +#include +#include +#include +#include "index_html.h" +#include "../../Arduino/src/i2cshare.h" + + +/* create this file and add your wlan credentials + const char* ssid = "MyWLANSID"; + const char* password = "MYPASSWORD"; +*/ +#include "../../../../private/credentials.h" + + +// switch relay sync to the lamp +// e.g. the Wifi Relay Board U4648 +#define USERELAY + + +// Relay Board parameters +#define ESP8266_GPIO2 2 // Blue LED. +#define ESP8266_GPIO4 4 // Relay control. +#define ESP8266_GPIO5 5 // Optocoupler input. +#define LED_PIN ESP8266_GPIO2 + +EspSaveCrash SaveCrash; +// the buffer to put the Crash log to +char *_debugOutputBuffer; + + +SHCIState lastState; + +// webserver on port 80 +AsyncWebServer server(80); + +unsigned long nextStateCall = millis(); +unsigned long lasti2cmsgtime = millis(); + + +// switch GPIO4 und GPIO2 sync to the lamp +void onStatusChanged(){ + //see https://ucexperiment.wordpress.com/2016/12/18/yunshan-esp8266-250v-15a-acdc-network-wifi-relay-module/ + //Setting GPIO4 high, causes the relay to close the NO contact with +#ifdef USERELAY + bool lamp = lastState.valid && lastState.lampOn; + digitalWrite( ESP8266_GPIO4, lamp ); + digitalWrite(LED_PIN, lamp); +#endif +} + + + + +// setup mcu +void setup(){ + + lastState.valid = false; + lastState.reserved = 0xAB; + + // Setup I2C Master on UART Pins to use relayboard + //ESP 8266 PIN 1(TX0) and PIN 3 (RX0) + Wire.begin(1,3); + + _debugOutputBuffer = (char *) calloc(2048, sizeof(char)); + + //setup wifi + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + WiFi.setAutoReconnect(true); + while (WiFi.status() != WL_CONNECTED) { + delay(100); + } + + // setup http server + server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ + AsyncWebServerResponse *response = request->beginResponse_P( 200, "text/html", index_html,sizeof(index_html)); + response->addHeader("Content-Encoding","deflate"); + request->send(response); + }); + + server.on("/status", HTTP_GET, [](AsyncWebServerRequest *request){ + + AsyncResponseStream *response = request->beginResponseStream("application/json"); + DynamicJsonDocument root(1024); + root["valid"] = lastState.valid; + root["doorstate"] = lastState.doorState; + root["doorposition"] = lastState.doorCurrentPosition; + root["doortarget"] = lastState.doorTargetPosition; + root["lamp"] = lastState.lampOn; + root["debug"] = lastState.reserved; + root["cc"] = lastState.cc; + root["lastresponse"] = millis()-lasti2cmsgtime; + + serializeJson(root,*response); + request->send(response); + }); + + server.on("/command", HTTP_GET, [] (AsyncWebServerRequest *request) { + if (request->hasParam("action")) { + int actionid = request->getParam("action")->value().toInt(); + switch (actionid){ + case I2C_CMD_CLOSEDOOR: + case I2C_CMD_OPENDOOR: + case I2C_CMD_OPENDOORHALF: + case I2C_CMD_STOPDOOR: + case I2C_CMD_VENTPOS: + case I2C_CMD_TOGGLELAMP: + Wire.beginTransmission(I2CADDR); + Wire.write((unsigned char)actionid); + Wire.endTransmission(); + break; + + default: + break; + } + } + request->send(200, "text/plain", "OK"); + }); + + server.on("/crashinfo", HTTP_GET, [] (AsyncWebServerRequest *request){ + strcpy(_debugOutputBuffer, ""); + SaveCrash.print(_debugOutputBuffer,2048); + if (request->hasParam("clear")) { + SaveCrash.clear(); + } + request->send(200, "text/plain", _debugOutputBuffer); + }); + + server.on("/sysinfo", HTTP_GET, [] (AsyncWebServerRequest *request) { + char buffer[150]; + rst_info* rinfo = ESP.getResetInfoPtr(); + + AsyncResponseStream *response = request->beginResponseStream("application/json"); + DynamicJsonDocument root(1024); + root["freemem"] = ESP.getFreeHeap(); + root["hostname"] = WiFi.hostname(); + root["ip"] = WiFi.localIP().toString(); + root["ssid"] = String(ssid); + root["wifistatus"] = WiFi.status(); + root["resetreason"] =ESP.getResetReason(); + root["errors"] = rinfo->exccause; + + //The address of the last crash is printed, which is used to + sprintf(buffer, "epc1=0x%08x, epc2=0x%08x, epc3=0x%08x, excvaddr=0x%08x, depc=0x%08x, exccause=0x%x, reason=0x%x", + rinfo->epc1, rinfo->epc2, rinfo->epc3, rinfo->excvaddr, rinfo->depc, rinfo->exccause, rinfo->reason); + root["rstinfo"] = buffer; + serializeJson(root,*response); + + request->send(response); + }); + + AsyncElegantOTA.begin(&server); + server.begin(); + + //setup relay board +#ifdef USERELAY + pinMode( ESP8266_GPIO4, OUTPUT ); // Relay control pin. + pinMode( ESP8266_GPIO5, INPUT_PULLUP ); // Input pin. + pinMode( LED_PIN, OUTPUT ); // ESP8266 module blue L + digitalWrite( ESP8266_GPIO4, 0 ); + digitalWrite(LED_PIN,0); +#endif + +} + +void loop(){ + if(nextStateCall < millis()){ + Wire.requestFrom(I2CADDR, sizeof(SHCIState)); + if(sizeof(SHCIState) != Wire.readBytes((unsigned char*) &lastState, sizeof(SHCIState))){ + lasti2cmsgtime = millis(); + onStatusChanged(); + } + nextStateCall = millis()+200; + } + AsyncElegantOTA.loop(); +} \ No newline at end of file diff --git a/HCPBridgeCombo/ESP/src/webpage/buildindex.cmd b/HCPBridgeCombo/ESP/src/webpage/buildindex.cmd new file mode 100644 index 0000000..6ed0ebd --- /dev/null +++ b/HCPBridgeCombo/ESP/src/webpage/buildindex.cmd @@ -0,0 +1 @@ +python compress.py diff --git a/HCPBridgeCombo/ESP/src/webpage/command b/HCPBridgeCombo/ESP/src/webpage/command new file mode 100644 index 0000000..e69de29 diff --git a/HCPBridgeCombo/ESP/src/webpage/compress.py b/HCPBridgeCombo/ESP/src/webpage/compress.py new file mode 100644 index 0000000..5e9faa8 --- /dev/null +++ b/HCPBridgeCombo/ESP/src/webpage/compress.py @@ -0,0 +1,35 @@ +#pip install htmlmin +#or python -m pip install htmlmin +#pip install jsmin +#or python -m pip install jsmin + +import gzip +import zlib +import htmlmin +from jsmin import jsmin + + + +content = "" +with open('index.html','rt',encoding="utf-8") as f: + content=f.read() + + +content = htmlmin.minify(content, remove_comments=True, remove_empty_space=True, remove_all_empty_space=True, reduce_empty_attributes=True, reduce_boolean_attributes=False, remove_optional_attribute_quotes=True, convert_charrefs=True, keep_pre=False) + + +import re +regex = r"" ,content, 0, re.DOTALL) + +result ="" +for c in zlib.compress(content.encode("UTF-8"),9): + result= result + ("0x%02X" %c) + if len(result)> 0: + result=result + "," + + +with open('../index_html.h',"wt") as f: + f.write("const uint8_t index_html[] PROGMEM = {"); + f.write(result.strip(",")) + f.write("};"); \ No newline at end of file diff --git a/HCPBridgeCombo/ESP/src/webpage/index.html b/HCPBridgeCombo/ESP/src/webpage/index.html new file mode 100644 index 0000000..303cbef --- /dev/null +++ b/HCPBridgeCombo/ESP/src/webpage/index.html @@ -0,0 +1,159 @@ + + + Garagentor Steuerung + + + + + + +

Garagentor

+ +

warte auf Verbindung.

+ +
+ +
+

Licht

+
+ + + + \ No newline at end of file diff --git a/HCPBridgeCombo/ESP/src/webpage/runtestserver.cmd b/HCPBridgeCombo/ESP/src/webpage/runtestserver.cmd new file mode 100644 index 0000000..092262b --- /dev/null +++ b/HCPBridgeCombo/ESP/src/webpage/runtestserver.cmd @@ -0,0 +1 @@ +python -m http.server diff --git a/HCPBridgeCombo/ESP/src/webpage/status b/HCPBridgeCombo/ESP/src/webpage/status new file mode 100644 index 0000000..c050664 --- /dev/null +++ b/HCPBridgeCombo/ESP/src/webpage/status @@ -0,0 +1,9 @@ +{ + "valid" : true, + "doorstate" : 1, + "doorposition" : 0, + "doortarget" : 0, + "lamp" : true, + "debug" : 0, + "lastresponse" : 0 +} \ No newline at end of file diff --git a/HCPBridgeCombo/ESP/test/README b/HCPBridgeCombo/ESP/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/HCPBridgeCombo/ESP/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html