1 /*
2 * File: Events.cpp
3 * ONLY for usage with eHouse system controllers | Intellectual property of iSys.Pl
4 * eHouse4Ethernet Server - described in UdpListener.cpp
5 * eHouse1 (RS-485) Server //described in rs485.cpp
6 * eHouse1 under CommManager Supervision Server - described in UdpListener.cpp
7 * TCP Client for submitting events to Ethernet eHouse Controllers and eHouse 1 via CommManager in case of eHouse under CM supervision version described in TcpClient.c
8 *
9 * EventQueue Process
10 *
11 * Author: Robert Jarzabek, iSys.Pl
12 * http://en.isys.pl/ eHouse Home automation Producer Web Page
13 * http://eHouse.biz/ eHouse Home automation SHOP
14 * http://smart.ehouse.pro/ eHouse Home Automation - Do it yourself, programming examples, designing
15 * Recently updated 11.11.2017
16 * globals.h - global configuration / main settings
17 * most important params for eHouse events manager
18 *
19 * COMMANAGER_IP_HIGH - set CommManager Ip addr h if differs from 192.168.0.254 (192.168.%COMMANAGER_IP_HIGH%.%COMMANAGER_IP_LOW%)
20 * COMMANAGER_IP_LOW - set CommManager Ip addr l
21 * EHOUSE_PRO_HIGH - default eHouse Pro Server IP addr h (0)
22 * EHOUSE_PRO_LOW - default eHouse Pro Server IP addr l (150)
23 * RE_SEND_RETRIES - No of retries in case of execution failure
24 * RE_TIME_REPLAY - Timer for retry in (RE_TIME_RETRY-RE_SEND_RETRIES) *0.1s
25 *
26 * Events.cpp - Event Queue processing
27 Recent update: 2018-08-16
28 */
29
30 #include "stdafx.h"
31 #include "../../main/Logger.h"
32 #include "../eHouseTCP.h"
33 #ifndef WIN32
34 #else
35 #endif
36 #include "globals.h"
37 #include "status.h"
38
39 /////////////////////////////////////////////////////////////////////////////////
GetIndexOfEvent(unsigned char * TempEvent)40 signed int eHouseTCP::GetIndexOfEvent(unsigned char *TempEvent)
41 {
42 unsigned int i;
43 for (i = 0; i < EVENT_QUEUE_MAX; i++)
44 {
45 if (memcmp(TempEvent, (struct EventQueueT *) &m_EvQ[i]->LocalEventsToRun, EVENT_SIZE) == 0)
46 return i; //Exist on Event Queue
47 }
48 return -1;
49 }
50
51 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
ExecQueuedEvents(void)52 void eHouseTCP::ExecQueuedEvents(void)
53 {
54 unsigned int i;
55 unsigned char localy = 1;
56 m_DisablePerformEvent = 0;
57 if (!m_EventsCountInQueue) return; //nothing availabla - we don't waste time here
58 m_EventsCountInQueue = 0;
59 for (i = 0; i < EVENT_QUEUE_MAX; i++)
60 {
61 if (m_EvQ[i]->LocalEventsToRun[2]) //not empty event
62 {
63 m_EventsCountInQueue++;
64 if (m_EvQ[i]->LocalEventsTimeOuts == RUN_NOW) //Should be Performed Right Now !!!
65 {
66 if (m_EvQ[i]->LocalEventsDrop) _log.Log(LOG_STATUS, "[Perform Queue Event] Q[%d] Now -> Retry: %d", i, m_EvQ[i]->LocalEventsDrop);
67 m_EvQ[i]->LocalEventsDrop++; //retries in case of failure
68 if (m_EvQ[i]->LocalEventsDrop > RE_SEND_RETRIES) //to much retries (no controller or no communication)
69 {
70 if (m_DEBUG_TCPCLIENT) _log.Log(LOG_STATUS, "[Exec Event] Q[%d] Drop Event", i);
71 memset(m_EvQ[i], 0, sizeof(EventQueueT)); //delete event permanently and immediatelly
72 }
73 else
74 {
75 ExecEvent(i); //Send event to hardware
76 break;
77 }
78 }
79 else
80 if (m_EvQ[i]->LocalEventsTimeOuts) //scheduled event
81 m_EvQ[i]->LocalEventsTimeOuts--; //decrement timer
82 else //Timer reach 0 - remove event from Queue
83 {
84 memset(m_EvQ[i], 0, sizeof(EventQueueT));
85 if (m_DEBUG_TCPCLIENT) _log.Log(LOG_STATUS, "[Exec Event] Remove Event");
86 }
87 }
88 }
89 }
90 //////////////////////////////////////////////////////////////////////////////////
91 /*
92 * Exec Event from EventsQueue EvQ[i]
93 *
94 *
95 */
ExecEvent(unsigned int i)96 void eHouseTCP::ExecEvent(unsigned int i)
97 {
98 unsigned char devh, devl;
99 unsigned char EventBuff[255];
100 unsigned int EventBuffSize;
101 unsigned int EventSize;
102 unsigned char EventsToRun[MAX_EVENTS_IN_PACK + 10];
103 unsigned int m = 0;
104 EventBuffSize = 0;
105 EventSize = 0;
106 devh = m_EvQ[i]->LocalEventsToRun[0]; //get address from DirectEvent
107 devl = m_EvQ[i]->LocalEventsToRun[1];
108 int ind = IndexOfEthDev(devh, devl); //should be transmited directly to controller or not?
109 if (ind == 0) //Via eHouse Pro Server
110 {
111 //printf("[Exec Event] RS-485, CAN, RF via PRO \r\n");
112 int mmm = 0;
113 for (m = 0; m < EVENT_QUEUE_MAX; m++) //for all events in queue
114 {
115 if ((IndexOfEthDev(devh, devl) == 0) && (m_EvQ[m]->LocalEventsTimeOuts == RUN_NOW)) //group all events in the queue for the same controller scheduled for sending
116 {
117 m_EvQ[m]->LocalEventsTimeOuts = RE_TIME_REPLAY; //Retry timer interval - next time if failed
118 memcpy(&EventBuff[EventBuffSize], m_EvQ[m]->LocalEventsToRun, EVENT_SIZE); //Add to send buffer
119 // printf("[ via PRO ] %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\r\n",EvQ[m].LocalEventsToRun[0],EvQ[m].LocalEventsToRun[1],EvQ[m].LocalEventsToRun[2],EvQ[m].LocalEventsToRun[3],EvQ[m].LocalEventsToRun[4],EvQ[m].LocalEventsToRun[5],EvQ[m].LocalEventsToRun[6],EvQ[m].LocalEventsToRun[7],EvQ[m].LocalEventsToRun[8],EvQ[m].LocalEventsToRun[9]);
120 EventBuffSize += EVENT_SIZE;
121 EventsToRun[EventSize] = m;
122 EventSize++;
123 if (EventSize >= MAX_EVENTS_IN_PACK) break; //As many events as possible
124 }
125 }
126 SendTCPEvent(EventBuff, EventSize, m_SrvAddrH, m_SrvAddrL, EventsToRun); //Submit via tcp client to desired Ethernet eHouse controller
127 return;
128 }
129 else
130 {
131 // printf("[Exec Event] Ethernet \r\n");
132 memset(&EventBuff, 0, sizeof(EventBuff));
133 EventSize = 0;
134 memset(EventsToRun, 0, sizeof(EventsToRun));
135 int mmm = 0;
136 for (m = 0; m < EVENT_QUEUE_MAX; m++)
137 {
138 if ((m_EvQ[m]->LocalEventsToRun[0] == devh) && (m_EvQ[m]->LocalEventsToRun[1] == devl) && (m_EvQ[m]->LocalEventsTimeOuts == RUN_NOW))
139 {
140 // printf("[Directly ] %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\r\n",EvQ[m].LocalEventsToRun[0],EvQ[m].LocalEventsToRun[1],EvQ[m].LocalEventsToRun[2],EvQ[m].LocalEventsToRun[3],EvQ[m].LocalEventsToRun[4],EvQ[m].LocalEventsToRun[5],EvQ[m].LocalEventsToRun[6],EvQ[m].LocalEventsToRun[7],EvQ[m].LocalEventsToRun[8],EvQ[m].LocalEventsToRun[9]);
141 m_EvQ[m]->LocalEventsTimeOuts = RE_TIME_REPLAY; //Retry timer interval
142 memcpy(&EventBuff[EventBuffSize], m_EvQ[m]->LocalEventsToRun, EVENT_SIZE); //Add to send buffer
143 EventBuffSize += EVENT_SIZE;
144 EventsToRun[EventSize] = m; //We store index of events to control it
145 EventSize++;
146 if (EventSize >= MAX_EVENTS_IN_PACK) break; //As many events as possible
147 }
148 }
149 SendTCPEvent(EventBuff, EventSize, devh, devl, EventsToRun); //Submit via tcp client to desired Ethernet eHouse controller
150 }
151 }
152 ///////////////////////////////////////////////////////////////////////////////////////////
153 //
154 // convert hex string to unsigned char with offset and value checking for text events
155 //
156 ///////////////////////////////////////////////////////////////////////////////////////////
hex2bin(const unsigned char * st,int offset)157 signed int eHouseTCP::hex2bin(const unsigned char *st, int offset)
158 {
159 char i;
160 int tmp = 0;
161 for (i = 0; i < 2; i++)
162 {
163 tmp = tmp << 4;
164 i = st[offset];
165 if ((i >= 'A') && (i <= 'F')) tmp += i - 'A' + 10;
166 else if ((i >= 'a') && (i <= 'f')) tmp += i - 'a' + 10;
167 else if ((i >= '0') && (i <= '9')) tmp += i - '0';
168 else return -1;
169 offset++;
170 }
171 return tmp;
172 }
173
174 /////////////////////////////////////////////////////////////////////////////////
175 // add multiple events to event queue - stored in text format with validation
176 ////////////////////////////////////////////////////////////////////////////////
AddTextEvents(unsigned char * ev,int size)177 void eHouseTCP::AddTextEvents(unsigned char *ev, int size)
178 {
179 unsigned char i = 0;
180 unsigned char offset = 0;
181 unsigned char evnt[EVENT_SIZE + 1];
182 if (size < 20) return; //ignore if tho short
183 while (offset < size - 1)
184 {
185 int tmp = hex2bin(ev, offset); // decode Text Hex Coded Event
186 if (tmp >= 0) // valid hex char
187 evnt[i] = (unsigned char)tmp; // construct binary
188 else
189 return; //ignore if wrong data (non hex digit)
190 i++;
191 if (i == 10) //only if valid eHouse text event 10 binary = 20 hex char event
192 {
193 i = 0;
194 AddToLocalEvent(evnt, 0); //add to queue
195 }
196 offset += 2;
197 }
198 }
199
200
201
202 /**
203 * AddEvent To Event Queue
204 * param: Even buffer of events - offset shift in buffer to copy
205 */
206
207
208 ///////////////////////////////////////////////////////////////////////////////////
209 // Add Event to Queue for Buffering and Multiple Event Submissions - binary mode
210 //////////////////////////////////////////////////////////////////////////////////
AddToLocalEvent(unsigned char * Even,unsigned char offset)211 signed int eHouseTCP::AddToLocalEvent(unsigned char *Even, unsigned char offset)
212 { //start
213 signed int i;
214 //signed int k;
215 unsigned char Event[EVENT_SIZE + 1];
216 memcpy(Event, (unsigned char *)&Even[offset], EVENT_SIZE); //copy event from selected offset
217 if (Event[2] == 0) return 0;
218 if (Event[2] == 0xff) return 0;
219 i = GetIndexOfEvent(Event);
220 _log.Log(LOG_STATUS, "[Add Event]: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", Event[0], Event[1], Event[2], Event[3], Event[4], Event[5], Event[6], Event[7], Event[8], Event[9]);
221
222 if (i >= 0) //event already exists in EventQueue
223 {
224 if (m_EvQ[i]->LocalEventsTimeOuts >= RUN_NOW) //Wasn't confirmed - No Successful Execution so far
225 {
226
227 }
228 else m_EvQ[i]->LocalEventsTimeOuts = RUN_NOW - 1; //Increase time of event not to disappear from queue if it recently run
229 m_EventsCountInQueue++;
230 if (m_DEBUG_TCPCLIENT) _log.Log(LOG_STATUS, "[Add Event] Already Exists Q[%d]", i);
231 return i;
232 }
233 //Event was not found in event Queue
234 for (i = 0; i < EVENT_QUEUE_MAX; i++)
235 {
236 if (!m_EvQ[i]->LocalEventsToRun[2]) // Free space then add
237 {
238 if (m_DEBUG_TCPCLIENT) _log.Log(LOG_STATUS, "[Add Event] Adding Q[%d]", i);
239 memcpy(&m_EvQ[i]->LocalEventsToRun, Event, EVENT_SIZE);
240 m_EventsCountInQueue++; //Event count in queue to perform EventQueue
241 m_EvQ[i]->LocalEventsTimeOuts = RUN_NOW; //Immediate Run
242 m_EvQ[i]->LocalEventsDrop = 0; //First try
243 m_EvQ[i]->iface = 0; //local interface not a gateway
244 if (m_EvQ[i]->LocalEventsToRun[0] == m_SrvAddrH)
245 m_EvQ[i]->iface = EV_ETHERNET_EVENT;
246 else m_EvQ[i]->iface = EV_VIA_EHOUSE_PRO;
247 return i;
248 }
249 }
250 if (m_DEBUG_TCPCLIENT) _log.Log(LOG_STATUS, "[Add Event] End of proc");
251 return -1;
252 }
253