WWW.DUMAIS.IO
ARTICLES
OVERLAY NETWORKS WITH MY SDN CONTROLLERSIMPLE LEARNING SWITCH WITH OPENFLOWINSTALLING KUBERNETES MANUALLYWRITING A HYPERVISOR WITH INTEL VT-X CREATING YOUR OWN LINUX CONTAINERSVIRTIO DRIVER IMPLEMENTATIONNETWORKING IN MY OSESP8266 BASED IRRIGATION CONTROLLERLED STRIP CONTROLLER USING ESP8266.OPENVSWITCH ON SLACKWARESHA256 ASSEMBLY IMPLEMENTATIONPROCESS CONTEXT ID AND THE TLBTHREAD MANAGEMENT IN MY HOBBY OSENABLING MULTI-PROCESSORS IN MY HOBBY OSNEW HOME AUTOMATION SYSTEMINSTALLING AND USING DOCKER ON SLACKWARESYSTEM ON A CHIP EMULATORUSING JSSIP AND ASTERISK TO MAKE A WEBPHONEC++ WEBSOCKET SERVERSIP ATTACK BANNINGBLOCK CACHING AND WRITEBACKBEAGLEBONE BLACK BARE METAL DEVELOPEMENTARM BARE METAL DEVELOPMENTUSING EPOLLMEMORY PAGINGIMPLEMENTING HTTP DIGEST AUTHENTICATIONSTACK FRAME AND THE RED ZONE (X86_64)AVX/SSE AND CONTEXT SWITCHINGHOW TO ANSWER A QUESTION THE SMART WAY.REALTEK 8139 NETWORK CARD DRIVERREST INTERFACE ENGINECISCO 1760 AS AN FXS GATEWAYHOME AUTOMATION SYSTEMEZFLORA IRRIGATION SYSTEMSUMP PUMP MONITORINGBUILDING A HOSTED MAILSERVER SERVICEI AM NOW HOSTING MY OWN DNS AND MAIL SERVERS ON AMAZON EC2DEPLOYING A LAYER3 SWITCH ON MY NETWORKACD SERVER WITH RESIPROCATEC++ JSON LIBRARYIMPLEMENTING YOUR OWN MUTEX WITH CMPXCHGWAKEUPCALL SERVER USING RESIPROCATEFFT ON AMD64CLONING A HARD DRIVECONFIGURING AND USING KVM-QEMUUSING COUCHDBINSTALLING COUCHDB ON SLACKWARENGW100 MY OS AND EDXS/LSENGW100 - MY OSASTERISK FILTER APPLICATIONCISCO ROUTER CONFIGURATIONAASTRA 411 XML APPLICATIONSPA941 PHONEBOOKSPEEDTOUCH 780 DOCUMENTATIONAASTRA CONTACT LIST XML APPLICATIONAVR32 OS FOR NGW100ASTERISK SOUND INJECTION APPLICATIONNGW100 - DIFFERENT PROBLEMS AND SOLUTIONSAASTRA PRIME RATE XML APPLICATIONSPEEDTOUCH 780 CONFIGURATIONUSING COUCHDB WITH PHPAVR32 ASSEMBLY TIPAP7000 AND NGW100 ARCHITECTUREAASTRA WEATHER XML APPLICATIONNGW100 - GETTING STARTEDAASTRA ALI XML APPLICATION

NEW HOME AUTOMATION SYSTEM

2015-08-05

DHAS

During the past months, I've been working on my Home Automation System. I did some major refactoring and moved away from the rPi. I am now running my home automation software on a x86-64 server.

The projects is hosted on github at https://github.com/pdumais/dhas.

The system uses a modular architecture now. I like to think of DHAS as a hub for different technologies. Since my home automation system is mix of Insteon devices, ethernet relays and temperature sensors, IP phones, and more, I made a central software that can interface with all those technologies. Each module is responsible for interfacing with one technology. on github, you will find these modules under the src/module folder. Everytime I need to add a new kind of module, I just create the class and it automatically gets instanciated and used. The modules register their own REST callbacks and the REST engine being self-documenting will show the newly added functions when querying the help API. This way, the system doesn't know anything about its modules. It only knows that it is running modules. So adding new modules becomes very easy because the work is isolated from the rest of the system.

The most simple module to look at is the Weather Module.

Arduino

Since I am not using the rPi anymore, I needed to find a way to get GPIOs on the server. So I bought an Arduino Leonardo and made a very simple firmware that presents the device as a CDC device using the LUFA library. The source code for the firmware is here:

main.c

#include "usblib.h" #include #include #define STABLE 100 uint8_t currentData = 0; /* Sent byte to host: bit Arduino pin AVR Pin 0 2 PD1 1 4 PD4 2 7 PE6 3 8 PB4 4 12 PD6 relays: 'a' -> arduino 10 -> PB6 ; 'a' = ON, 'A' = off 'b' -> arduino 11 -> PB7 ; 'b' = ON, 'B' = off to test the live stream: cat /dev/ttyACM0 | xxd -c1 */ void setCurrentData(uint8_t data) { currentData = data; } void sendCurrentData() { SendCDCChar(currentData); } int main(void) { uint8_t pb,pd,pe; uint8_t newData = 0; uint8_t lastData = 0; char stabilizerCount = -1; InitCDC(); sei(); // Set pins as pullups PORTB |= ((1<<4)); PORTD |= ((1<<1)|(1<<4)|(1<<6)); PORTE |= ((1<<6)); // Set pins as input DDRB &= ~((1<<4)); DDRD &= ~((1<<1)|(1<<4)|(1<<6)); DDRE &= ~((1<<6)); // set PB6 and PB6 as output DDRB |= (1<<6)|(1<<7); PORTB |= (1<<6)|(1<<7); // initially off (high = off) uint8_t receivedChar; while (1) { pb = PINB; pd = PIND; pe = PINE; newData = ~(((pd>>1)&1)|(((pd>>4)&1)<<1)|(((pe>>6)&1)<<2)|(((pb>>4)&1)<<3)|(((pd>>6)&1)<<4)); newData &= 0x1F; // clear 3 top bits since we don't use them if (GetCDCChar(&receivedChar)) { if (receivedChar == '?') { sendCurrentData(); } else if (receivedChar == 'A') { PORTB |= (1<<6); } else if (receivedChar == 'B') { PORTB |= (1<<7); } else if (receivedChar == 'a') { PORTB &= ~(1<<6); } else if (receivedChar == 'b') { PORTB &= ~(1<<7); } } // debounce if (lastData != newData) { lastData=newData; stabilizerCount = STABLE; } if (stabilizerCount>0) stabilizerCount--; if (stabilizerCount==0) { stabilizerCount=-1; if (currentData != newData) { setCurrentData(newData); sendCurrentData(); } } CDCWork(); } }

usblib.c

#include "usblib.h" #include #include #include #include #include "Descriptors.h" #include #include #include #include #include USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = { .Config = { .ControlInterfaceNumber = INTERFACE_ID_CDC_CCI, .DataINEndpoint = { .Address = CDC_TX_EPADDR, .Size = CDC_TXRX_EPSIZE, .Banks = 1, }, .DataOUTEndpoint = { .Address = CDC_RX_EPADDR, .Size = CDC_TXRX_EPSIZE, .Banks = 1, }, .NotificationEndpoint = { .Address = CDC_NOTIFICATION_EPADDR, .Size = CDC_NOTIFICATION_EPSIZE, .Banks = 1, }, }, }; void CDCWork() { CDC_Device_USBTask(&VirtualSerial_CDC_Interface); USB_USBTask(); } uint8_t GetCDCChar(uint8_t* data) { int16_t r = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); if (r >= 0) { *data = r; return 1; } return 0; } void SendCDCChar(uint8_t data) { Endpoint_SelectEndpoint(VirtualSerial_CDC_Interface.Config.DataINEndpoint.Address); CDC_Device_SendByte(&VirtualSerial_CDC_Interface, data); } void InitCDC() { MCUSR &= ~(1 << WDRF); wdt_disable(); clock_prescale_set(clock_div_1); USB_Init(); } void EVENT_USB_Device_Connect(void) { } void EVENT_USB_Device_Disconnect(void) { } void EVENT_USB_Device_ConfigurationChanged(void) { bool ConfigSuccess = true; ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); } void EVENT_USB_Device_ControlRequest(void) { CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); } void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) { }