New Combo ESP8266 + Arduino Pro Mini via i2c
This commit is contained in:
		
							
								
								
									
										5
									
								
								HCPBridgeCombo/Arduino/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								HCPBridgeCombo/Arduino/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/.pio
 | 
				
			||||||
 | 
					.vscode/.browse.c_cpp.db*
 | 
				
			||||||
 | 
					.vscode/c_cpp_properties.json
 | 
				
			||||||
 | 
					.vscode/launch.json
 | 
				
			||||||
 | 
					.vscode/ipch
 | 
				
			||||||
							
								
								
									
										7
									
								
								HCPBridgeCombo/Arduino/.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								HCPBridgeCombo/Arduino/.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    // See http://go.microsoft.com/fwlink/?LinkId=827846
 | 
				
			||||||
 | 
					    // for the documentation about the extensions.json format
 | 
				
			||||||
 | 
					    "recommendations": [
 | 
				
			||||||
 | 
					        "platformio.platformio-ide"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								HCPBridgeCombo/Arduino/include/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								HCPBridgeCombo/Arduino/include/README
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										46
									
								
								HCPBridgeCombo/Arduino/lib/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								HCPBridgeCombo/Arduino/lib/README
									
									
									
									
									
										Normal file
									
								
							@@ -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 <Foo.h>
 | 
				
			||||||
 | 
					#include <Bar.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										20
									
								
								HCPBridgeCombo/Arduino/platformio.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								HCPBridgeCombo/Arduino/platformio.ini
									
									
									
									
									
										Normal file
									
								
							@@ -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 = 
 | 
				
			||||||
							
								
								
									
										415
									
								
								HCPBridgeCombo/Arduino/src/hciemulator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								HCPBridgeCombo/Arduino/src/hciemulator.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -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<millis()){
 | 
				
			||||||
 | 
					            m_statemachine = WAITING;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!m_skipFrame){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            processFrame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // send response
 | 
				
			||||||
 | 
					            if(m_txlen > 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<millis()){
 | 
				
			||||||
 | 
					                        m_txbuffer[7]= 0x01;
 | 
				
			||||||
 | 
					                        m_txbuffer[8]= 0x10;
 | 
				
			||||||
 | 
					                        m_statemachine = WAITING; 
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // close Door
 | 
				
			||||||
 | 
					                case STARTCLOSEDOOR:
 | 
				
			||||||
 | 
					                    m_txbuffer[7]= 0x02;
 | 
				
			||||||
 | 
					                    m_txbuffer[8]= 0x20;
 | 
				
			||||||
 | 
					                    m_statemachine = STARTCLOSEDOOR_RELEASE;
 | 
				
			||||||
 | 
					                    m_lastStateTime = millis();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case STARTCLOSEDOOR_RELEASE:
 | 
				
			||||||
 | 
					                    if(m_lastStateTime+SIMULATEKEYPRESSDELAYMS<millis()){
 | 
				
			||||||
 | 
					                        m_txbuffer[7]= 0x01;
 | 
				
			||||||
 | 
					                        m_txbuffer[8]= 0x20;
 | 
				
			||||||
 | 
					                        m_statemachine = WAITING; 
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;   
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // stop Door
 | 
				
			||||||
 | 
					                case STARTSTOPDOOR:
 | 
				
			||||||
 | 
					                    m_txbuffer[7]= 0x02;
 | 
				
			||||||
 | 
					                    m_txbuffer[8]= 0x40;
 | 
				
			||||||
 | 
					                    m_statemachine = STARTSTOPDOOR_RELEASE;
 | 
				
			||||||
 | 
					                    m_lastStateTime = millis();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case STARTSTOPDOOR_RELEASE:
 | 
				
			||||||
 | 
					                    if(m_lastStateTime+SIMULATEKEYPRESSDELAYMS<millis()){
 | 
				
			||||||
 | 
					                        m_txbuffer[7]= 0x01;
 | 
				
			||||||
 | 
					                        m_txbuffer[8]= 0x40;
 | 
				
			||||||
 | 
					                        m_statemachine = WAITING; 
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Ventilation
 | 
				
			||||||
 | 
					                case STARTVENTPOSITION:
 | 
				
			||||||
 | 
					                    m_txbuffer[7]= 0x02;
 | 
				
			||||||
 | 
					                    m_txbuffer[9]= 0x40;
 | 
				
			||||||
 | 
					                    m_statemachine = STARTVENTPOSITION_RELEASE;
 | 
				
			||||||
 | 
					                    m_lastStateTime = millis();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case STARTVENTPOSITION_RELEASE:
 | 
				
			||||||
 | 
					                    if(m_lastStateTime+SIMULATEKEYPRESSDELAYMS<millis()){
 | 
				
			||||||
 | 
					                        m_txbuffer[7]= 0x01;
 | 
				
			||||||
 | 
					                        m_txbuffer[9]= 0x40;
 | 
				
			||||||
 | 
					                        m_statemachine = WAITING; 
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Half Position
 | 
				
			||||||
 | 
					                case STARTOPENDOORHALF:
 | 
				
			||||||
 | 
					                    m_txbuffer[7]= 0x02;
 | 
				
			||||||
 | 
					                    m_txbuffer[9]= 0x04;
 | 
				
			||||||
 | 
					                    m_statemachine = STARTOPENDOORHALF_RELEASE;
 | 
				
			||||||
 | 
					                    m_lastStateTime = millis();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case STARTOPENDOORHALF_RELEASE:
 | 
				
			||||||
 | 
					                    if(m_lastStateTime+SIMULATEKEYPRESSDELAYMS<millis()){
 | 
				
			||||||
 | 
					                        m_txbuffer[7]= 0x01;
 | 
				
			||||||
 | 
					                        m_txbuffer[9]= 0x04;
 | 
				
			||||||
 | 
					                        m_statemachine = WAITING; 
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;                                          
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Toggle Lamp
 | 
				
			||||||
 | 
					                case STARTTOGGLELAMP:
 | 
				
			||||||
 | 
					                    m_txbuffer[7]= 0x10;
 | 
				
			||||||
 | 
					                    m_txbuffer[9]= 0x02;
 | 
				
			||||||
 | 
					                    m_statemachine = STARTTOGGLELAMP_RELEASE;
 | 
				
			||||||
 | 
					                    m_lastStateTime = millis();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case STARTTOGGLELAMP_RELEASE:
 | 
				
			||||||
 | 
					                    if(m_lastStateTime+SIMULATEKEYPRESSDELAYMS<millis()){
 | 
				
			||||||
 | 
					                        m_txbuffer[7]= 0x08;
 | 
				
			||||||
 | 
					                        m_txbuffer[9]= 0x02;
 | 
				
			||||||
 | 
					                        m_statemachine = WAITING; 
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;  
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                case WAITING:
 | 
				
			||||||
 | 
					                    break;            
 | 
				
			||||||
 | 
					            }                                 
 | 
				
			||||||
 | 
					            return;             
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if(m_rxbuffer[5] == 0x02){
 | 
				
			||||||
 | 
					            //      00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
 | 
				
			||||||
 | 
					            //0011: 02 17 9C B9 00 02 9C 41 00 02 04 0F 04 17 00 7B 21
 | 
				
			||||||
 | 
					            //res=> 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										117
									
								
								HCPBridgeCombo/Arduino/src/hciemulator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								HCPBridgeCombo/Arduino/src/hciemulator.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					#ifndef __hciemulator_h
 | 
				
			||||||
 | 
					#define __hciemulator_h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <Stream.h>
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
							
								
								
									
										26
									
								
								HCPBridgeCombo/Arduino/src/i2cshare.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								HCPBridgeCombo/Arduino/src/i2cshare.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					#ifndef __i2cshare_h
 | 
				
			||||||
 | 
					#define __i2cshare_h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
							
								
								
									
										61
									
								
								HCPBridgeCombo/Arduino/src/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								HCPBridgeCombo/Arduino/src/main.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <Wire.h>
 | 
				
			||||||
 | 
					#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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								HCPBridgeCombo/Arduino/test/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								HCPBridgeCombo/Arduino/test/README
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										5
									
								
								HCPBridgeCombo/ESP/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								HCPBridgeCombo/ESP/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/.pio
 | 
				
			||||||
 | 
					.vscode/.browse.c_cpp.db*
 | 
				
			||||||
 | 
					.vscode/c_cpp_properties.json
 | 
				
			||||||
 | 
					.vscode/launch.json
 | 
				
			||||||
 | 
					.vscode/ipch
 | 
				
			||||||
							
								
								
									
										7
									
								
								HCPBridgeCombo/ESP/.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								HCPBridgeCombo/ESP/.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    // See http://go.microsoft.com/fwlink/?LinkId=827846
 | 
				
			||||||
 | 
					    // for the documentation about the extensions.json format
 | 
				
			||||||
 | 
					    "recommendations": [
 | 
				
			||||||
 | 
					        "platformio.platformio-ide"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								HCPBridgeCombo/ESP/include/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								HCPBridgeCombo/ESP/include/README
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										46
									
								
								HCPBridgeCombo/ESP/lib/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								HCPBridgeCombo/ESP/lib/README
									
									
									
									
									
										Normal file
									
								
							@@ -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 <Foo.h>
 | 
				
			||||||
 | 
					#include <Bar.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										19
									
								
								HCPBridgeCombo/ESP/platformio.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								HCPBridgeCombo/ESP/platformio.ini
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										1
									
								
								HCPBridgeCombo/ESP/src/index_html.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								HCPBridgeCombo/ESP/src/index_html.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										180
									
								
								HCPBridgeCombo/ESP/src/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								HCPBridgeCombo/ESP/src/main.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
				
			|||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include "EspSaveCrash.h"
 | 
				
			||||||
 | 
					#include <ESPAsyncWebServer.h>
 | 
				
			||||||
 | 
					#include <AsyncElegantOTA.h>
 | 
				
			||||||
 | 
					#include <AsyncJson.h>
 | 
				
			||||||
 | 
					#include <ArduinoJson.h>
 | 
				
			||||||
 | 
					#include <Wire.h>
 | 
				
			||||||
 | 
					#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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								HCPBridgeCombo/ESP/src/webpage/buildindex.cmd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								HCPBridgeCombo/ESP/src/webpage/buildindex.cmd
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					python compress.py
 | 
				
			||||||
							
								
								
									
										0
									
								
								HCPBridgeCombo/ESP/src/webpage/command
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								HCPBridgeCombo/ESP/src/webpage/command
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										35
									
								
								HCPBridgeCombo/ESP/src/webpage/compress.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								HCPBridgeCombo/ESP/src/webpage/compress.py
									
									
									
									
									
										Normal file
									
								
							@@ -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"<script>(.+?)<\/script>"
 | 
				
			||||||
 | 
					content = re.sub(regex, lambda x: "<script>"+jsmin(x.group(1))+"</script>" ,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("};");
 | 
				
			||||||
							
								
								
									
										159
									
								
								HCPBridgeCombo/ESP/src/webpage/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								HCPBridgeCombo/ESP/src/webpage/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE HTML><html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					  <title>Garagentor Steuerung</title>
 | 
				
			||||||
 | 
					  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
					  <meta charset="UTF-8">
 | 
				
			||||||
 | 
					  <link rel="icon" href="data:,">
 | 
				
			||||||
 | 
					  <style>
 | 
				
			||||||
 | 
					    html {font-family: Arial; display: inline-block; text-align: center;}
 | 
				
			||||||
 | 
					    h2 {font-size: 3.0rem;}
 | 
				
			||||||
 | 
					    p {font-size: 3.0rem;}
 | 
				
			||||||
 | 
					    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
 | 
				
			||||||
 | 
					    .switch {position: relative; display: inline-block; width: 80px; height: 48px} 
 | 
				
			||||||
 | 
					    .switch input {display: none}
 | 
				
			||||||
 | 
					    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}
 | 
				
			||||||
 | 
					    .slider:before {position: absolute; content: ""; height: 32px; width: 32px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}
 | 
				
			||||||
 | 
					    input:checked+.slider {background-color: #b30000}
 | 
				
			||||||
 | 
					    input:checked+.slider:before {-webkit-transform: translateX(32px); -ms-transform: translateX(32px); transform: translateX(32px)}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						.button {
 | 
				
			||||||
 | 
							border: 4px;
 | 
				
			||||||
 | 
							border-style: solid;
 | 
				
			||||||
 | 
							color: black;
 | 
				
			||||||
 | 
							width: 100px;
 | 
				
			||||||
 | 
							height: 100px;
 | 
				
			||||||
 | 
							text-align: center;
 | 
				
			||||||
 | 
							display: inline;
 | 
				
			||||||
 | 
							text-decoration: none;
 | 
				
			||||||
 | 
							display: inline-block;
 | 
				
			||||||
 | 
							font-weight: bold;
 | 
				
			||||||
 | 
							font-size: 20px;
 | 
				
			||||||
 | 
							margin: 4px 2px;
 | 
				
			||||||
 | 
							cursor: pointer;
 | 
				
			||||||
 | 
							border-radius: 50px;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.buttonred {border-color: #ED5961;}
 | 
				
			||||||
 | 
						.buttonyellow {border-color: #fcca00;}
 | 
				
			||||||
 | 
						.buttongreen {border-color: #48bd81;}  
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <h2>Garagentor</h2>  
 | 
				
			||||||
 | 
						<canvas width="250px" height="250px" id="dc"></canvas>
 | 
				
			||||||
 | 
						<h3 id="status">warte auf Verbindung.</h3>	
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<hr/>
 | 
				
			||||||
 | 
						<button class="button buttonred" onclick="doCommand(1)">Auf</button> <button class="button buttonyellow" onclick="doCommand(2)">Stop</button> <button class="button buttongreen" onclick="doCommand(0)">Zu</button>
 | 
				
			||||||
 | 
						<hr/>
 | 
				
			||||||
 | 
						<h4>Licht</h4><label class="switch"><input type="checkbox" onchange="doCommand(5)" id="light"><span class="slider"></span></label>
 | 
				
			||||||
 | 
						<hr/>
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						doorpos = 10;
 | 
				
			||||||
 | 
						dir = -1;
 | 
				
			||||||
 | 
						isconnected = false;
 | 
				
			||||||
 | 
						var animation;
 | 
				
			||||||
 | 
						function startDoorAnimation() {
 | 
				
			||||||
 | 
							if(!animation){
 | 
				
			||||||
 | 
								animation = setInterval(Draw, 200);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						function stopDoorAnimation() {
 | 
				
			||||||
 | 
							if(animation){
 | 
				
			||||||
 | 
								clearInterval(animation);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							animation = null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						function Draw(){		
 | 
				
			||||||
 | 
							var svg =document.getElementById("svg");
 | 
				
			||||||
 | 
							var dc = document.getElementById("dc");		
 | 
				
			||||||
 | 
							var ctx = dc.getContext("2d");
 | 
				
			||||||
 | 
							width = dc.width;
 | 
				
			||||||
 | 
							height = dc.height;
 | 
				
			||||||
 | 
							ctx.clearRect(0, 0, width, height);		
 | 
				
			||||||
 | 
							xa= [18,18,10,3,174,347,340,332,332,297,297,52,52,18];
 | 
				
			||||||
 | 
							ya= [327,114,117,100,22,100,117,114,327,327,112,112,327,327];
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							ctx.fillStyle = "black";
 | 
				
			||||||
 | 
							ctx.beginPath();
 | 
				
			||||||
 | 
							for (i =0;i<xa.length;i++){			
 | 
				
			||||||
 | 
								if(i==0){
 | 
				
			||||||
 | 
									ctx.moveTo((xa[i]/350) * width , (ya[i]/350)*width);
 | 
				
			||||||
 | 
								}else{
 | 
				
			||||||
 | 
									ctx.lineTo((xa[i]/350) * width, (ya[i]/350)*width);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx.fill();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for(i=0;i<doorpos;i++){			
 | 
				
			||||||
 | 
								ctx.fillRect((62/350) * width, ((120+21*i)/350) * width, (225/350) * width, (18/350) * width);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							doorpos+=dir;	
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if(dir<0 && doorpos<=0){
 | 
				
			||||||
 | 
								dir=dir*-1;			
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if(dir>0 &&doorpos>=10){
 | 
				
			||||||
 | 
								dir=dir*-1;			
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						function doCommand(action) {
 | 
				
			||||||
 | 
					      if(!isconnected){return;}
 | 
				
			||||||
 | 
						  var xhr = new XMLHttpRequest();
 | 
				
			||||||
 | 
						  xhr.open("GET", "/command?action="+action, true); 	  
 | 
				
			||||||
 | 
						  xhr.send();
 | 
				
			||||||
 | 
						}  
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						function setDoorState(state){
 | 
				
			||||||
 | 
							stopDoorAnimation();		
 | 
				
			||||||
 | 
							if(state == 0) {doorpos = 10;dir = -1};
 | 
				
			||||||
 | 
							if(state == 1) {doorpos = 0; dir = 1};		
 | 
				
			||||||
 | 
							if(state == 2) {doorpos = 5; dir = 1};		
 | 
				
			||||||
 | 
							Draw();		
 | 
				
			||||||
 | 
							if(state == 3) startDoorAnimation();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						function getStatusText(id){
 | 
				
			||||||
 | 
							result = "Das Tor "
 | 
				
			||||||
 | 
							switch(id)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								case 0x20: setDoorState(1); return result+"ist geöffnet.";
 | 
				
			||||||
 | 
								case 0x40: setDoorState(0); return result+"ist geschlossen.";
 | 
				
			||||||
 | 
								case 0x80: setDoorState(2); return result+"ist teilgeöffnet.";
 | 
				
			||||||
 | 
								case 0x00: setDoorState(2); return result+"ist teilgeöffnet.";
 | 
				
			||||||
 | 
								case 0x02: setDoorState(3); return result+"schließt.";
 | 
				
			||||||
 | 
								case 0x01: setDoorState(3); return result+"öffnet.";
 | 
				
			||||||
 | 
								case -1: setDoorState(0); return "keine Verbindung zum Tor.";
 | 
				
			||||||
 | 
								default: return "unbekanter Status: " + id;
 | 
				
			||||||
 | 
							}    
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						function updateData(){
 | 
				
			||||||
 | 
								var xmlhttp = new XMLHttpRequest();
 | 
				
			||||||
 | 
								xmlhttp.onreadystatechange = function() {
 | 
				
			||||||
 | 
								  if (this.readyState == 4 && this.status == 200) {
 | 
				
			||||||
 | 
									var status = JSON.parse(this.responseText);	
 | 
				
			||||||
 | 
					                isconnected = status.valid;
 | 
				
			||||||
 | 
									document.getElementById("status").innerHTML = getStatusText(status.valid?status.doorstate:-1);
 | 
				
			||||||
 | 
									document.getElementById("light").checked = status.lamp & status.valid;
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								  }
 | 
				
			||||||
 | 
								  isconnected= false;
 | 
				
			||||||
 | 
								};			
 | 
				
			||||||
 | 
								xmlhttp.open("GET", "/status", true);
 | 
				
			||||||
 | 
								xmlhttp.send();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						Draw();
 | 
				
			||||||
 | 
						updateData();	
 | 
				
			||||||
 | 
						setInterval(updateData, 3000);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										1
									
								
								HCPBridgeCombo/ESP/src/webpage/runtestserver.cmd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								HCPBridgeCombo/ESP/src/webpage/runtestserver.cmd
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					python -m http.server 
 | 
				
			||||||
							
								
								
									
										9
									
								
								HCPBridgeCombo/ESP/src/webpage/status
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								HCPBridgeCombo/ESP/src/webpage/status
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "valid" : true,
 | 
				
			||||||
 | 
					  "doorstate" : 1,
 | 
				
			||||||
 | 
					  "doorposition" : 0,
 | 
				
			||||||
 | 
					  "doortarget" : 0,
 | 
				
			||||||
 | 
					  "lamp" : true,
 | 
				
			||||||
 | 
					  "debug" : 0,
 | 
				
			||||||
 | 
					  "lastresponse" : 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								HCPBridgeCombo/ESP/test/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								HCPBridgeCombo/ESP/test/README
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user