Statistics
| Revision:

root / logic / trunk / src / startup / main.c @ 62

History | View | Annotate | Download (10.6 KB)

1 10 Janez1
/*
2
 * main.c
3
 *
4
 * 2011, Aleksander Besir (alex.besir@gmail.com)
5
 *
6
 */
7 62 Janez1
#include <stdio.h>
8
#include <stdlib.h>
9
#include <pthread.h>
10
#include <syslog.h>
11
#include "../hci_comm/hciChanged.h"
12 10 Janez1
#include "../hci_comm/hci_comm.h"
13 37 Janez1
#include "../init/scenariolist.h"
14
#include "../init/devicelist.h"
15 60 Janez1
#include "../logics/device_threads.h"
16 40 Janez1
//#include "../logics/scenario_threads.h"
17 10 Janez1
18
// Inter-thread shared variables
19
// TODO: These variables could be configuration variables
20
//       (eg: static boolean loggingEnabled)
21 62 Janez1
static device           *hDevice;       //device list
22
static scenario         *hScenario;     //scenario list
23 60 Janez1
static thread_id_holder *hThrIDhold_dev;//holds IDs of running threads (devices)
24
static thread_id_holder *hThrIDhold_scn;//holds IDs of running threads (scenarios)
25 40 Janez1
//extern scenario *test;   //device list
26
27 10 Janez1
// Crtitical section mutual exclusion security
28 57 alexbesir
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
29 60 Janez1
pthread_t       decisionMakingThread;
30
pthread_t       hciConnectionThread;
31 10 Janez1
32 57 alexbesir
// Global variable to check, if HCI made any changes that need
33
// to be updated by the logic.
34
// Changing this variable's value must be done using the
35
// mutex mtx declared before.
36
// To change variables value you should do this:
37
//    pthread_mutex_lock(&mtx);
38
//    hciChanged = 0;
39
//    pthread_mutex_unlock(&mtx);
40
// The meaning of hciChanged possible values is in hci_comm/hciChanged.h.
41
// HCI should always reset hciChanged value to HCI_CHANGED_RESET after
42
// checking it's value.
43
// To use mtx and hciChanged variables in other .c files, write
44
//    extern int hciChanged;
45
//    extern pthread_mutex_t mtx;
46
// on top of the class.
47
48
int hciChanged = HCI_CHANGED_RESET;
49
50 10 Janez1
void *decisionMakingThread_routine(void *dummy);
51
void *hciConnectionThread_routine(void *dummy);
52 40 Janez1
void *randomValThread_routine(void *dummy);
53
void *scenarioThread_routine(void *dummy);
54 60 Janez1
int  reinitialiseLogic(); // on HCI request
55 62 Janez1
int  shutDownLogic();
56 10 Janez1
57
// Application entry point
58
int main(int argc, char *argv[]) {
59 62 Janez1
    /** //DAEMON
60
    pid_t pid, sid;
61 10 Janez1

62 62 Janez1
    pid = fork();
63
    if (pid < 0) {
64
            exit(EXIT_FAILURE);
65
    }
66
    // EXIT PARENT
67
    if (pid > 0) {
68
            exit(EXIT_SUCCESS);
69
    }
70

71
    //umask(0);
72

73
    // Open any logs here
74

75
    // Create a new SID for the child process
76
    sid = setsid();
77
    if (sid < 0) {
78
            // Log the failure
79
            exit(EXIT_FAILURE);
80
    }
81

82
    // Close out the standard file descriptors
83
    // Because daemons generally dont interact directly with user so there is no need of keeping these open
84
    close(STDIN_FILENO);
85
    close(STDOUT_FILENO);
86
    close(STDERR_FILENO);
87
    /**/
88 31 Janez1
    /* initialisation */
89 37 Janez1
    hDevice   = setDeviceList();
90 44 Janez1
    hScenario = setNewScenarioList(hDevice);
91 31 Janez1
92 37 Janez1
    printf("Devices present:\t%d\n",   getNumberOfDevices());
93
    printf("Scenarios present:\t%d\n", getNumberOfScenarios());
94
95 31 Janez1
    /* regular work */
96 21 Janez1
    //*
97 37 Janez1
        pthread_create(&hciConnectionThread, NULL,hciConnectionThread_routine, NULL);
98 10 Janez1
        pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
99
100
        pthread_join(hciConnectionThread,NULL);
101 60 Janez1
        //pthread_join(decisionMakingThread,NULL);
102 21 Janez1
    /**/
103 10 Janez1
        exit(0);
104
}
105
106
// Decision-making thread routine
107
// Should just call a function that implements decision making module of the logic
108
void *decisionMakingThread_routine(void *dummy) {
109 40 Janez1
    printf("-- decisionMakingThread_routine started --\n");
110 10 Janez1
111 37 Janez1
    /**dummy threads for input devices (sensors)**/
112 60 Janez1
    hThrIDhold_dev = NULL;
113
    thread_id_holder *t_holder, *t_holder_old; //just for list of IDs creation, for both scenarios and devices
114
    t_holder_old = NULL;
115 10 Janez1
116 37 Janez1
    int i;
117
    for(i=0; i<getNumberOfDevices(); i++)
118
    {
119 60 Janez1
        t_holder = (thread_id_holder *)malloc(sizeof(thread_id_holder));
120
        pthread_create(&t_holder->pthr_idx,NULL,randomValThread_routine,NULL);
121 37 Janez1
122 60 Janez1
        t_holder->nxt=NULL;
123
        if(t_holder_old!=NULL)
124
            t_holder_old->nxt=t_holder;
125
        t_holder_old=t_holder;
126
127
        if(hThrIDhold_dev==NULL)
128
            hThrIDhold_dev=t_holder_old;
129 37 Janez1
    }
130
131
    /**start scenario threads**/
132 60 Janez1
    t_holder_old = NULL;
133
    hThrIDhold_scn=NULL;
134 37 Janez1
135
    for(i=0; i<getNumberOfScenarios(); i++)
136
    {
137 60 Janez1
        t_holder = (thread_id_holder *)malloc(sizeof(thread_id_holder));
138
        pthread_create(&t_holder->pthr_idx,NULL,scenarioThread_routine,NULL);
139 37 Janez1
140 60 Janez1
        t_holder->nxt=NULL;
141
        if(t_holder_old!=NULL)
142
            t_holder_old->nxt=t_holder;
143
        t_holder_old=t_holder;
144 37 Janez1
145 60 Janez1
        if(hThrIDhold_scn==NULL)
146
            hThrIDhold_scn=t_holder_old;
147 37 Janez1
    }
148
149
    /*start some sort of control over scenarios? - hmm morda ne...bom jutri :)*/
150 60 Janez1
    printf("Exiting main thread\n");
151 10 Janez1
        pthread_exit(0);
152
}
153
154
// HCI connection thread routine
155
// Start listening to some port
156
void *hciConnectionThread_routine(void *dummy) {
157 37 Janez1
    printf("hciConnectionThread_routine started\n");
158 10 Janez1
        int hciErrorCode = listenTo(1100);
159
160
        pthread_exit(0);
161 37 Janez1
}
162 10 Janez1
163 40 Janez1
// scenario thread routine
164 37 Janez1
void *scenarioThread_routine(void *dummy)
165
{
166
    scenario *scen;
167 40 Janez1
    device   *inDev;
168
    int      active = 0;
169 44 Janez1
    float    scenarioBuffer;
170 60 Janez1
    //printf("My scen ID> %ld\n",pthread_self());
171 44 Janez1
172 40 Janez1
    /*load scenario*/
173 37 Janez1
    scen = getAvailableScenario(hScenario);
174
    if(!scen) pthread_exit(0);
175
176 40 Janez1
    // TODO add pointer to this device (all of them actually) to scenario structure - problems with segfault
177 44 Janez1
    //indev = scen->inDev;
178 40 Janez1
    inDev = getDevice(hDevice, scen->inDevice_id);
179 44 Janez1
    scen->buf=inDev->buf;
180
    printf("Scenario %s buffer updated to %.2f!\n", scen->scen_id, inDev->buf);
181 37 Janez1
    //set its value
182 40 Janez1
    //*
183 37 Janez1
    while(1) //TODO signal == true
184
    {
185 40 Janez1
        /// main scenario loop
186
        //printf("inDev->buf %.2f\n", 1.0f*inDev->buf);
187
        if(active)
188
            sleep(scen->actvChkItv);
189
        else
190
            sleep(scen->idleChkItv);
191
        //checking primary condition
192 44 Janez1
        if(scen->buf) // is not null
193 40 Janez1
        {
194 44 Janez1
            scen->buf = scen->buf*scen->alpha+inDev->buf*(1-scen->alpha);
195
            //printf("Scenario %s buffer updated to %f, alpha: %.2f!\n", scen->scen_id, scenarioBuffer, scen->alpha);
196
            syslog(LOG_MAIL, "%s:%.2f", scen->inDevice_id, scen->buf);
197 40 Janez1
            active = 1;
198
199 44 Janez1
            if((scen->buf > scen->optval + scen->tolval) ||
200
               (scen->buf < scen->optval - scen->tolval))
201 40 Janez1
            {
202
                if(evaluateAdditionalConditions(scen->cond_l, hDevice))
203 41 Janez1
                {
204 44 Janez1
                    // TODO syslog - "action:scen_ID:power_percentage"
205
                    int power = getPowerPercentage(scen->minval, scen->maxval, scen->optval, &scen->buf, scen->func);
206 62 Janez1
207
                    /// Forking to execute action!
208
                    pid_t pid, sid;
209
210
                    pid = fork();
211
                    if (pid < 0) {
212
                            exit(EXIT_FAILURE);
213
                    }
214
                    // ignore parent
215
                    if (pid > 0) {}
216
                    else
217
                    {
218
                        /*TODO execute action with parameter(s)*/
219
                        syslog(LOG_MAIL, "%s:%s:%.2f", scen->action, scen->scen_id, power);
220
221
                        execl(scen->action, power);
222
                        printf("Zaganjam napravo %s z mocjo %d\n", scen->scen_id, power);
223
224
                        shutDownLogic();
225
                    }
226
227 41 Janez1
                }
228 40 Janez1
                else
229
                    printf("Scenario %s not updated!\n", scen->scen_id);
230
            }
231
            else
232
                active = 0;
233
        }
234 44 Janez1
        /*
235 40 Janez1
        if(active)
236 44 Janez1
            printf("%s main buffer %.2f, sleeping %d\n",scen->scen_id, scen->buf, scen->actvChkItv);
237 40 Janez1
        else
238 44 Janez1
            printf("%s main buffer %.2f, sleeping %d\n",scen->scen_id, scen->buf, scen->idleChkItv);
239
        /**/
240 37 Janez1
    }
241 40 Janez1
    /**/
242 37 Janez1
           pthread_exit(0);
243 10 Janez1
}
244 37 Janez1
245
void *randomValThread_routine(void *dummy)
246
{
247
    //get device
248
    device *dev;
249
    dev = getAvailableDevice(hDevice);
250
    if(dev){}
251
    else
252
        pthread_exit(0);
253
    //set its value
254
    while(1) //TODO signal == true
255
    {
256 62 Janez1
        dev->buf=random()%10+20;// random 20-30
257 40 Janez1
        //printf("device %s buf = %d\n", dev->id, dev->buf);
258 37 Janez1
        sleep(dev->readitv);
259
    }
260
           pthread_exit(0);
261
}
262 40 Janez1
263 60 Janez1
void freeDeviceList(device *dev)
264
{
265
    if(dev->nxt!=NULL)
266
        freeDeviceList(dev->nxt);
267
    free(dev);
268
}
269
270
void freeScenarioList(scenario *scn)
271
{
272
    if(scn->nxt!=NULL)
273
        freeScenarioList(scn->nxt);
274
    free(scn);
275
}
276
277
void freeThreadIDList(thread_id_holder *tih)
278
{
279
    if(tih->nxt!=NULL)
280
        freeThreadIDList(tih->nxt);
281
    free(tih);
282
}
283
284
int reinitialiseLogic()
285
{
286
    thread_id_holder *hold;
287
    hold = hThrIDhold_dev;
288
    //hThrIDhold_dev = NULL;
289
290
    //kill device threads
291
    printf("Attempting to cancel threads!\n");
292
    while(hold)
293
    {
294
        printf("Cancelling dev thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
295
        //TODO free thread_id_holder list too!
296
        hold=hold->nxt;
297
    }
298
299
    //kill scenario threads
300
    hold = hThrIDhold_scn;
301
    //hThrIDhold_scn = NULL;
302
    while(hold)
303
    {
304
        printf("Cancelling scn thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
305
        //TODO free thread_id_holder list too!
306
        hold=hold->nxt;
307
    }
308
309
    //free memory
310
    printf("Freeing memory!\n");
311
    freeDeviceList(hDevice);
312
    freeScenarioList(hScenario);
313
    freeThreadIDList(hThrIDhold_dev);
314
    freeThreadIDList(hThrIDhold_scn);
315
316
    //reinit devices
317
    printf("Reinitializing devices!\n");
318
    hDevice   = setDeviceList();
319
320
    //reinit scenarios
321
    printf("Reinitializing scenarios!\n");
322
    hScenario = setNewScenarioList(hDevice);
323
324
    //restart main thread
325
    printf("Restarting main thread!\n");
326
        pthread_create(&decisionMakingThread,NULL,decisionMakingThread_routine,NULL);
327
328
        return 1; //sucess, TODO add fail conditions
329
}
330 62 Janez1
331
int shutDownLogic()
332
{
333
    thread_id_holder *hold;
334
    hold = hThrIDhold_dev;
335
    //hThrIDhold_dev = NULL;
336
337
    //kill device threads
338
    printf("Attempting to cancel threads!\n");
339
    while(hold)
340
    {
341
        printf("Cancelling dev thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
342
        //TODO free thread_id_holder list too!
343
        hold=hold->nxt;
344
    }
345
346
    //kill scenario threads
347
    hold = hThrIDhold_scn;
348
    //hThrIDhold_scn = NULL;
349
    while(hold)
350
    {
351
        printf("Cancelling scn thread %ld with return state %d\n", hold->pthr_idx,pthread_cancel(hold->pthr_idx));
352
        //TODO free thread_id_holder list too!
353
        hold=hold->nxt;
354
    }
355
356
    //free memory
357
    printf("Freeing memory!\n");
358
    freeDeviceList(hDevice);
359
    freeScenarioList(hScenario);
360
    freeThreadIDList(hThrIDhold_dev);
361
    freeThreadIDList(hThrIDhold_scn);
362
363
    //stop main thread and HCI comm thread
364
    pthread_cancel(decisionMakingThread);
365
    pthread_cancel(hciConnectionThread);
366
367
        return 1; //sucess, TODO add fail conditions
368
}