Statistics
| Revision:

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

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

66 62 Janez1
    pid = fork();
67
    if (pid < 0) {
68
            exit(EXIT_FAILURE);
69
    }
70
    // EXIT PARENT
71
    if (pid > 0) {
72
            exit(EXIT_SUCCESS);
73
    }
74

75
    //umask(0);
76

77
    // Open any logs here
78

79
    // Create a new SID for the child process
80
    sid = setsid();
81
    if (sid < 0) {
82
            // Log the failure
83
            exit(EXIT_FAILURE);
84
    }
85

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