UserLibSimulator  1
Librería para E/S de simuladores genéricos
UserLibSimulator.c
1 #include "UserLibSimulator.h"
2 
3 #include "AlMar_mongoose-7-6.h"
4 #include <pthread.h>
5 #include "cJSON.h"
6 
7 static struct mg_mgr _mgr; // Event manager
8 static pthread_t _mgr_thread; // Event thread
9 static pthread_mutex_t _mgr_mutex=PTHREAD_MUTEX_INITIALIZER;
10 void* WssCheckSimulatorThread(void* param);
11 
12 #define MAX_AD_INPUTS 8
13 #define MAX_COUNTER_INPUTS 8
14 #define MAX_AD_OUTPUTS 8
15 #define MAX_PWM_OUTPUTS 8
16 
18 {
19  bool changed;
20  int dOut;
21  int nDA,daValue[MAX_AD_OUTPUTS];
22  int nPWM,pWmValue[MAX_PWM_OUTPUTS],pwmPeriod[MAX_PWM_OUTPUTS];
23 };
24 
26 {
27  bool changed;
28  int dIn;
29  int nAD,adValue[MAX_AD_INPUTS];
30  int nCounter,counterValue[MAX_COUNTER_INPUTS];
31 };
32 
33 
34 static struct ComputerState
35 {
36  struct ComputerOutputs out;
37  struct ComputerInputs in;
38 } _computerStateThread,_computerStateUser;
39 
40 
41 void WssEventHandler(struct mg_connection *conn, int ev,
42  void *ev_data, void *fn_data)
43 {
44  static int lastEv=-1;
45 // if (ev!=2 || ev!=lastEv) {
46 // printf("EVENT NUMBER %d\n",ev); fflush(stdout);
47 // }
48  switch (ev)
49  {
50  case MG_EV_CONNECT:
51  {
52 #if MG_ENABLE_OPENSSL
53  struct mg_tls_opts opts = {.ca = NULL};
54  mg_tls_init(conn, &opts);
55 #endif
56  break;
57  }
58  case MG_EV_HTTP_MSG:
59  {
60  struct mg_http_message *hm = (struct mg_http_message *) ev_data;
61  mg_ws_upgrade(conn,hm,NULL);
62  break;
63  }
64  case MG_EV_WS_OPEN:
65  {
66  printf("WS Open\n"); fflush(stdout);
67  *((bool*) fn_data)=true;
68  break;
69  }
70  case MG_EV_WS_MSG:
71  {
72  struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
73 // printf("WS Message: %.*s\n",wm->data.len,wm->data.ptr); fflush(stdout);
74 
75  cJSON* json=cJSON_ParseWithLength(wm->data.ptr,wm->data.len);
76  pthread_mutex_lock(&_mgr_mutex);
77  if (json!=NULL)
78  {
79  _computerStateThread.in.changed=true;
80  for (int j=0;j<cJSON_GetArraySize(json);j++)
81  {
82  cJSON* item=cJSON_GetArrayItem(json,j);
83  int iAD;
84  const char* name=cJSON_GetStringValue(cJSON_GetObjectItem(item,"name"));
85  const char* iotype=cJSON_GetStringValue(cJSON_GetObjectItem(item,"iotype"));
86  if (iotype==NULL || strlen(iotype)==0)
87  continue;
88  if (strncmp(iotype,"ad",2)==0)
89  {
90  int iAD=atoi(iotype+2);
91  if (iAD>=0 && iAD<_computerStateThread.in.nAD)
92  {
93  _computerStateThread.in.adValue[iAD]=cJSON_GetNumberValue(cJSON_GetObjectItem(item,"value"));
94  continue;
95  }
96  }
97 
98  else if (strncmp(iotype,"di",2)==0)
99  {
100  int iDI=atoi(iotype+2);
101  if (cJSON_IsTrue(cJSON_GetObjectItem(item,"value")))
102  _computerStateThread.in.dIn |= (1<<iDI);
103  else
104  _computerStateThread.in.dIn &= ~(1<<iDI);
105  continue;
106  }
107  }
108  }
109  pthread_mutex_unlock(&_mgr_mutex);
110  cJSON_Delete(json);
111  break;
112  }
113  case MG_EV_CLOSE:
114  {
115  printf("WS Close\n"); fflush(stdout);
116  break;
117  }
118 
119  }
120  lastEv=ev;
121 }
122 
123 #include <psapi.h>
124 bool ProcessIsPresent(const char* procName)
125 {
126  DWORD idProcess[1024];
127  DWORD nProcesses;
128  bool found=false;
129  if (! EnumProcesses(idProcess,1024*sizeof(DWORD),&nProcesses))
130  {
131  return false;
132  }
133  nProcesses/=sizeof(DWORD);
134  for (int j=0;j<nProcesses && ! found;j++)
135  {
136  if (idProcess[j]!=0)
137  {
138  HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
139  PROCESS_VM_READ,
140  FALSE, idProcess[j] );
141 
142  // Get the process name.
143 
144  if (hProcess!=NULL )
145  {
146  HMODULE hMod;
147  DWORD cbNeeded;
148  char processName[1024];
149  int count;
150  if (count=GetProcessImageFileNameA(hProcess,processName,1024),count>0)
151  {
152  char* ptEnd=processName+count-strlen(procName);
153  if (strcmp(ptEnd,procName)==0 && ptEnd[-1]=='\\' )
154  found=true;
155  }
156  CloseHandle( hProcess );
157  }
158  }
159  }
160  return found;
161 }
162 
163 int Simulator_ConnectWss(const char* appName,const char* userName,const char* passwd,const char* ip_address,int port)
164 {
165  memset(&_computerStateThread,0,sizeof(struct ComputerState));
166  memset(&_computerStateUser,0,sizeof(struct ComputerState));
167 
168  if (! ProcessIsPresent("MongooseWebServer.exe"))
169  {
170  printf("Simulator error: ejecute MongooseWebServer.exe antes de intentar la conexion\n"); fflush(stdout);
171  return CONNECT_ERROR_SERVER_NOT_RUNNING;
172  }
173 
174  // TODO: from jSON or XML
175  _computerStateThread.in.nAD=_computerStateUser.in.nAD=4;
176 
177  bool done = false; // Event handler flips it to true
178  struct mg_connection *c; // Client connection
179  mg_mgr_init(&_mgr); // Initialise event manager
180 
181  char s_url[256],user_pwd[256],user_pwd_base64[64+1];
182 #if MG_ENABLE_OPENSSL
183  sprintf(s_url,"wss://%s:%d/Apps/%s/wss/%s/",ip_address,port,appName,userName);
184 #else
185  sprintf(s_url,"ws://%s:%d/Apps/%s/wss/%s/",ip_address,port,appName,userName);
186 #endif
187  sprintf(user_pwd,"%s:%s",userName,passwd);
188  mg_base64_encode((const unsigned char*) user_pwd,strlen(user_pwd),user_pwd_base64);
189  c = mg_ws_connect(&_mgr, s_url, WssEventHandler, &done,"Authorization: Basic %.*s\r\n",64,user_pwd_base64); // Create client
190  int tries=0;
191  time_t t=time(NULL);
192  for (tries=0;tries < 10 && (c && done == false); tries++)
193  {
194  mg_mgr_poll(&_mgr, 1000); // Wait for echo
195  if (! done && time(NULL)-t > 2) {
196  printf("Simulator intentando conexion con %s\n",s_url); fflush(stdout);
197  c = mg_ws_connect(&_mgr, s_url, WssEventHandler, &done,"Authorization: Basic %.*s\r\n",64,user_pwd_base64); // Create client
198 
199  }
200 
201  }
202 
203  if (tries<10)
204  {
205  printf("Simulator conectado con %s\n",s_url); fflush(stdout);
206  pthread_create(&_mgr_thread,NULL,WssCheckSimulatorThread,NULL);
207  return CONNECT_IS_OK;
208  }
209  else
210  {
211  printf("Simulator no se puede conectar con %s. Compruebe configuracion\n",s_url); fflush(stdout);
212  return CONNECT_ERROR_SERVER_NOT_RESPONDING;
213  }
214 }
215 
216 //mg_mgr_free(&_mgr); // Deallocate resources
217 
218 void* WssCheckSimulatorThread(void* param)
219 {
220  while (1)
221  {
222  mg_mgr_poll(&_mgr, 5);
223  pthread_mutex_lock(&_mgr_mutex);
224  if (_computerStateThread.in.changed)
225  {
226  _computerStateThread.in.changed=false;
227  memcpy(&_computerStateUser.in,&_computerStateThread.in,sizeof(struct ComputerInputs));
228  }
229  if (_computerStateUser.out.changed)
230  {
231  cJSON* jsonOutput=cJSON_CreateObject();
232  if (_computerStateThread.out.dOut!=_computerStateUser.out.dOut)
233  {
234  cJSON_AddNumberToObject(jsonOutput,"do",_computerStateUser.out.dOut);
235  }
236  _computerStateUser.out.changed=false;
237  memcpy(&_computerStateThread.out,&_computerStateUser.out,sizeof(struct ComputerOutputs));
238  char* jsonTxt=cJSON_Print(jsonOutput);
239  for (struct mg_connection *ptConn=_mgr.conns;ptConn!=NULL;ptConn=ptConn->next)
240  {
241  if (ptConn->is_client && ptConn->is_websocket)
242  {
243  mg_ws_send(ptConn,jsonTxt,strlen(jsonTxt)+1,WEBSOCKET_OP_TEXT);
244  break;
245  }
246  }
247  free(jsonTxt);
248  cJSON_Delete(jsonOutput);
249  }
250  pthread_mutex_unlock(&_mgr_mutex);
251  }
252 }
253 
254 int Simulator_ReadAD(int ad_channel)
255 {
256  if (ad_channel<0 || ad_channel>=_computerStateUser.in.nAD)
257  return -1;
258  int v;
259  pthread_mutex_lock(&_mgr_mutex);
260  v=_computerStateUser.in.adValue[ad_channel];
261  pthread_mutex_unlock(&_mgr_mutex);
262  return v;
263 }
264 
265 
266 int Simulator_ReadDI()
267 {
268  int v;
269  pthread_mutex_lock(&_mgr_mutex);
270  v=_computerStateUser.in.dIn;
271  pthread_mutex_unlock(&_mgr_mutex);
272  return v;
273 }
274 
275 int Simulator_ReadDO()
276 {
277  int v;
278  pthread_mutex_lock(&_mgr_mutex);
279  v=_computerStateUser.out.dOut;
280  pthread_mutex_unlock(&_mgr_mutex);
281  return v;
282 }
283 
284 void Simulator_WriteDO(int value)
285 {
286  pthread_mutex_lock(&_mgr_mutex);
287  _computerStateUser.out.dOut=value;
288  _computerStateUser.out.changed=true;
289  pthread_mutex_unlock(&_mgr_mutex);
290 }
291 
292 
293 
294 void Simulator_Delay(int value_ms)
295 {
296  Sleep(value_ms);
297 }
298 
299 HANDLE hTimers[N_MAX_TIMERS]={NULL,NULL,NULL,NULL};
300 
301 VOID CALLBACK TimerCallback(PVOID lParam1,BOOLEAN timerOrWaitFired)
302 {
303  void (*userFn)() = (void (*)()) lParam1;
304  (*userFn)();
305 }
306 
307 int Simulator_SetTimerInterrupt(int timer_number, int tm_ms, void (*Fn)())
308 {
309  if (timer_number<0 || timer_number>=N_MAX_TIMERS)
310  return -1;
311  if (Fn==NULL && hTimers[timer_number]!=NULL)
312  {
313  DeleteTimerQueueTimer(NULL,hTimers[timer_number],NULL);
314  hTimers[timer_number]=NULL;
315  return 0;
316  }
317 
318 
319  //set the timer to call the timer routine in 2ms
320  if(!CreateTimerQueueTimer( &hTimers[timer_number], NULL, (WAITORTIMERCALLBACK) TimerCallback,(PVOID) Fn, 0,tm_ms,WT_EXECUTEINTIMERTHREAD))
321  {
322  printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
323  return -2;
324  }
325  return 0;
326 }
ComputerOutputs
Definition: UserLibSimulator.c:17
ComputerInputs
Definition: UserLibSimulator.c:25