/**
* @file main.cpp
* @author Volodymyr Shymanskyy
* @license This project is released under the MIT License (MIT)
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
* @date Mar 2015
* @brief
*/
//#define BLYNK_DEBUG
#define BLYNK_PRINT stdout
#ifdef RASPBERRY
#include <BlynkApiWiringPi.h>
#else
#include <BlynkApiLinux.h>
#endif
#include <BlynkSocket.h>
#include <BlynkOptionsParser.h>
static BlynkTransportSocket _blynkTransport;
BlynkSocket Blynk(_blynkTransport);
static const char *auth, *serv;
static uint16_t port;
#include <BlynkWidgets.h>
#include "HomeBridge.h"
WidgetTerminal TermExec(V11);
WidgetTerminal TermLog(V10);
// Sala update temperature reading
BLYNK_READ(V5) {
double Temp;
if(HomeBridge_TemperatureGet("TS1", &Temp) < 0) {
Blynk.virtualWrite(V11, "TS1 - Error on command execution\r\n");
} else {
Blynk.virtualWrite(V5, Temp1);
}
}
// Asilo update temperature reading
BLYNK_READ(V6) {
double Temp;
if(HomeBridge_TemperatureGet("TS2", &Temp) < 0) {
Blynk.virtualWrite(V11, "TS2 - Error on command execution\r\n");
} else {
Blynk.virtualWrite(V6, Temp2);
}
}
void setup()
{
Blynk.begin(auth, serv, port);
// Start Home Bridge thread
HomeBridge_Initialization();
}
void loop()
{
Blynk.run();
}
int main(int argc, char* argv[])
{
parse_options(argc, argv, auth, serv, port);
setup();
while(true) {
loop();
}
return 0;
}
/**************************HomeBridge.c**************************/
#include "HomeBridge.h"
/* Max 10 device attacched */
#define MAX_CONN_DEVICES 10
#define MSG_BUFFER_DIM 16
void HomeBridge_ServerHandler(void);
void HomeBridge_ClientHandler(void * sockFd);
void HomeBridge_LogStream(string LogDescr);
// Entry points thread funcitons
static void * HomeBridge_ServerHandlerEntryPoint(void * unused);
static void * HomeBridge_ClientHandlerEntryPoint(void * sockFd);
// pthread stuffs as global variables for module
pthread_t SrvThread;
pthread_t ClntThread;
/* Connected Devices list - SHARED VARIABLE */
static struct DeviceTable DeviceList[MAX_CONN_DEVICES];
/******************************************************************************/
void HomeBridge_Initialization(void) {
pthread_create(&SrvThread, NULL, HomeBridge_ServerHandlerEntryPoint, NULL);
}
/******************************************************************************/
int HomeBridge_TemperatureGet(char * devID, double * Temp) {
int i = 0;
int DataIndex;
bool Found = true;
// Get device list position
while(memcmp(DeviceList[i].Name, devID, sizeof(DeviceList[i].Name)) != 0) {
if(i >= MAX_CONN_DEVICES) {
Found = false;
cout<<"Device not found in list because not yet connected"<<endl;
break;
} else {
i++;
}
}
if(Found == true) {
// Get related data
DataIndex = ((DeviceList[i].DataIndex == 0) ? 1 : 0);
*Temp = DeviceList[i].Temperature[DataIndex];
return 0;
} else {
return -1;
}
}
/******************************************************************************/
int HomeBridge_EventQueueInsert(char * devID, char * Cmd) {
int i = 0;
bool Found = true;
// Get device list position
while(memcmp(DeviceList[i].Name, devID, sizeof(DeviceList[i].Name)) != 0) {
if(i >= MAX_CONN_DEVICES) {
Found = false;
cout<<"Device not found in list because not yet connected"<<endl;
break;
} else {
i++;
}
}
if(Found == true) {
// Wait untill previous command has been executed
while(DeviceList[i].NewCmd == true);
// Save connected device ID
memcpy(DeviceList[i].Command, Cmd, sizeof(DeviceList[i].Command));
DeviceList[i].NewCmd = true;
return 0;
} else {
return -1;
}
}
/******************************************************************************/
void HomeBridge_ClientHandler(void * sockFd) {
int i = 0u;
time_t Start = 0;
time_t Elapsed = 0;
// Get socked file descriptor
int socketFd = *(int *)sockFd;
char Buf[MSG_BUFFER_DIM];
// Create thread
pthread_detach(pthread_self());
// Get device list position
while(DeviceList[i].Sock != socketFd) {
i++;
}
// Send command to connected device
if(send(socketFd, "WHO", sizeof("WHO"), 0) < 0) {
cout<<"Node Identification sending error [fd ="<<socketFd<<"]"<<endl;
}
// Blocking receiving ID from connected device
if(recv(socketFd, Buf, MSG_BUFFER_DIM, 0) < 0) {
cout<<"Node Identification retrieving error [fd ="<<socketFd<<"]"<<endl;
} else {
// Save connected device ID
memcpy(DeviceList[i].Name, Buf, (sizeof(DeviceList[i].Name) - 1u));
DeviceList[i].Name[4] = '\0';
cout<<DeviceList[i].Name<<" Connected"<<endl;
}
// Get starting time
Start = time(NULL);
// Connection engaged
while(1) {
if(DeviceList[i].NewCmd == true) {
// Send command to connected device
if(send(socketFd, DeviceList[i].Command, sizeof(DeviceList[i].Command), 0) < 0) {
cout<<"["<<DeviceList[i].Name<<"]"<<"Data sending error [fd ="<<socketFd<<"]"<<endl;
}
// Blocking receiving ID from connected device
if(recv(socketFd, Buf, MSG_BUFFER_DIM, 0) < 0) {
cout<<"["<<DeviceList[i].Name<<"]"<<"Data retrieving error [fd ="<<socketFd<<"]"<<endl;
} else {
// Convert ASCII value to double
//DeviceList[i].Temperature = atof(Buf);
}
// Set queued command consumed
DeviceList[i].NewCmd = false;
sleep(100);
} else {
// Get temperature every 5 seconds
Elapsed = difftime(time(NULL), Start);
if(Elapsed > 5) {
// Send command to connected device
if(send(socketFd, "GET", sizeof("GET"), 0) < 0) {
cout<<"["<<DeviceList[i].Name<<"]"<<"Temperature sending error [fd ="<<socketFd<<"]"<<endl;
}
// Blocking receiving ID from connected device
if(recv(socketFd, Buf, MSG_BUFFER_DIM, 0) < 0) {
cout<<"["<<DeviceList[i].Name<<"]"<<"Temperature retrieving error [fd ="<<socketFd<<"]"<<endl;
} else {
// Convert ASCII value to double
DeviceList[i].DataIndex = ((DeviceList[i].DataIndex == 0) ? 1 : 0);
DeviceList[i].Temperature[DeviceList[i].DataIndex] = atof(Buf);
}
// Get new time
Start = time(NULL);
}
}
}
}
/******************************************************************************/
void HomeBridge_ServerHandler(void)
{
int DevIndex = 0u;
int serverSocket, newSocket;
struct sockaddr_in serverAddr, clientAddr;
socklen_t addr_size;
// Create thread
pthread_detach(pthread_self());
// Reset device list table
memset(DeviceList, 0, sizeof(DeviceList));
// Create the socket.
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if(serverSocket < 0)
HomeBridge_LogStream("Error on socket creation");
// Configure settings of the server address struct
bzero((char*) &serverAddr, sizeof(serverAddr));
// Address family = Internet
serverAddr.sin_family = AF_INET;
// Set port number, using htons function to use proper byte order
serverAddr.sin_port = htons((long)12001);
// Set IP address to localhost
serverAddr.sin_addr.s_addr = INADDR_ANY;
// Set all bits of the padding field to 0
//memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
// Bind the address struct to the socket
if(bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0)
HomeBridge_LogStream("Error on socket bind");
// Listen on the socket, with 10 max connection requests queued
if(listen(serverSocket, 10) < 0)
HomeBridge_LogStream("Error on listening");
while(1)
{
// Accept call creates a new socket for the incoming connection
newSocket = accept(serverSocket, (struct sockaddr *) &clientAddr, &addr_size);
if(newSocket != -1) {
if(DevIndex == (MAX_CONN_DEVICES - 1)) {
HomeBridge_LogStream("Too many devices already connected");
} else {
/* Save attached device */
DeviceList[DevIndex].Sock = newSocket;
DevIndex++;
if(pthread_create(&ClntThread, NULL, HomeBridge_ClientHandlerEntryPoint, (void *)&newSocket) != 0) {
HomeBridge_LogStream("Failed to create Client thread");
}
}
} else {
HomeBridge_LogStream("Error on socket accept");
}
}
}
/******************************************************************************/
void HomeBridge_LogStream(string LogDescr) {
int mrk;
char LogData[64];
// Initialize date time
time_t Time = time(NULL);
struct tm *DateTime = localtime(&Time);
// Format output log string
mrk = strftime(LogData, sizeof(LogData), "[%D - %H:%M:%S] ", DateTime);
strcpy(&LogData[mrk], LogDescr.c_str());
cout<<LogData<<endl;
}
/**************************************HomeBridge.h************************************/
#ifndef HOMEBRIDGE_H
#define HOMEBRIDGE_H
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/time.h>
using namespace std;
/* Attached device list */
struct DeviceTable {
int Sock;
char Name[4];
char Command[4];
int DataIndex;
double Temperature[2];
double Humidity;
double Power;
bool NewCmd;
};
extern void HomeBridge_Initialization(void);
extern int HomeBridge_EventQueueInsert(char * devID, char * Cmd);
extern int HomeBridge_TemperatureGet(char * devID, double * Temp);
/*extern void HomeBridge_HumidityGet(string devID, double * Hum);
extern void HomeBridge_EnergyGet(string devID, double * KWh);*/
#endif //HOMEBRIDGE_H