// /* mltask.c: XidarML tasks. Copyright (c) 1996 Eliot W. Dudley. All rights reserved. edudley@servtech.com XIDAR 3388 STATE RT 370 CATO NY 13033 You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the README file. */ /* 1-Wire, DS, DS1820, DS2405, DS2407, DS9097, and MicroLan are trademarks and/or registered trademarks of Dallas Semiconductor Coporation */ //============================================================================= #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <limits.h> #include <setjmp.h> #include <memory.h> #include <errno.h> #include <math.h> #include <time.h> #include <sys/time.h> #include "util.h" #include "mlfnc.h" #include "ml.h" #include "mld.h" #include "mlerr.h" //============================================================================= //============================================================================= #define T1820_SIZ 0x0200 //============================================================================= //============================================================================= // /*/ A simple demo of a XidarML task object that fires up and logs temperature readings from a DS1820. The original ml.rc command line would have been something like: spawn t1820log chickencoop tmlq tmlmsg chickencoop /data/temperature 1800 Which means start a task object using function T1820Log() and pass it the command: chickencoop tmlq tmlmsg chickencoop /data/temperature 1800 Which to T1820Log means to start a task named 'chickencoop' and talk to the task named 'tml' via message queue 'tmlq' and and message mailbox 'tmlmsg', and get data from the 1-Wire device also named 'chickencoop', log the data to the directory '/data/temperature' in file 'chickencoop. And log it every half hour. Source: \URL{../mltask.c.html#TS1820Log} */ int T1820Log( char *cmd, int pri_ret ) { int i; char *ptr; pML pml; pTCB ptcb; int delay = 0; char *file_name = 0; char *name= 0; pEVENT ptmlq = 0; pEVENT ptmlmsg = 0; int hist_idx = 0; long int temp[16]; struct timeval tv[16]; pMLNODE pmlnode; struct tm *ptm; FILE *LOG; MLREAD mlread; if(0 == setjmp((ptcb = TaskCreate(&cmd, T1820_SIZ))->jmp_buf)) { ptcb->pmsg = EventCreate(EVENT_NAME_DEFAULT, EVENT_MSG); ptmlq = GetEventByName(Shift(&cmd)); ptmlmsg = GetEventByName(Shift(&cmd)); MALLOC(name, strlen(ptr = Shift(&cmd)) + 1, char); strcpy(name, ptr); MALLOC(file_name, strlen(ptr = Shift(&cmd)) + strlen(name) + 2, char); strcat(strcat(strcpy(file_name, ptr), "/"), name); delay = (delay = atoi((ptr = Shift(&cmd)) ? ptr : "10")) ? delay : 10; SpawnRet(pri_ret, ptcb->name); } StackClr(ptcb); if (!(ptr = VAPost(ptmlq, ptcb->pmsg, strcpy(BufNew(), "MLGetpML")))) { Fatal(__LINE__, NULL_PTR, 0); } if (!(pml = *((pML *)ptr))) { Fatal(__LINE__, NULL_PTR, 0); } BufDelete(ptr); if (!(pmlnode = GetMLNodeByName(pml, name))) { Fatal(__LINE__, NULL_PTR, 0); } mlread = pmlnode->pmldriver->mlread; LOG = fopen(file_name, "a"); for (;;) { // Wait until our device comes around. EventPend(pmlnode->psem, 0); for (i = 0; i < 4; ++i) { if (0 > (mlread)(pml, pmlnode, (char *)0, 0, 0)) { MLPathCheck(pml); continue; } temp[hist_idx = (hist_idx + 1) & 7] = pmlnode->dev.ds1820.temp; tv[hist_idx] = pmlnode->tv; ptm = localtime((time_t *)&pmlnode->tv.tv_sec); VAPrintf(0, (VAPRINTF)vfprintf, LOG ,"%04d%02d%02d%02d%02d%02d %.3f\n" ,ptm->tm_year + 1900 ,ptm->tm_mon + 1 ,ptm->tm_mday ,ptm->tm_hour ,ptm->tm_min ,ptm->tm_sec ,pmlnode->dev.ds1820.temp / 65536.0 ); fflush(LOG); VAPrintf(0, (VAPRINTF)vfprintf, pexec->LOG ,"%04d%02d%02d%02d%02d%02d %8.3f %8.3f %s\n" ,ptm->tm_year + 1900 ,ptm->tm_mon + 1 ,ptm->tm_mday ,ptm->tm_hour ,ptm->tm_min ,ptm->tm_sec ,pmlnode->dev.ds1820.temp / 65536.0 ,32.0 + ((1.8 / 65536.0) * pmlnode->dev.ds1820.temp) ,name ); fflush(LOG); break; } EventSched(ptmlmsg, 0); TaskDelaySec(delay); } } //============================================================================= //============================================================================= int T1820CycleDetect( char *cmd, int pri_ret ) { int i; char *ptr; char *file_name = 0; char *name = 0; pTCB ptcb; pEVENT ptmlq = 0; pEVENT ptmlmsg = 0; pML pml; pMLNODE pmlnode; int delay = 0; int hist_idx; long int temp[16]; struct timeval tv[16]; struct tm *ptm; long int temp_min; long int temp_max; long int dtemp; long int dtemp_abs; long int dt; double dtemp_dt; double deadband = 0; int deadbandticks = 0; int init; MLREAD mlread; FILE *LOG; if(0 == setjmp((ptcb = TaskCreate(&cmd, T1820_SIZ))->jmp_buf)) { ptcb->pmsg = EventCreate(EVENT_NAME_DEFAULT, EVENT_MSG); ptmlq = GetEventByName(Shift(&cmd)); ptmlmsg = GetEventByName(Shift(&cmd)); MALLOC(name, strlen(ptr = Shift(&cmd)) + 1, char); strcpy(name, ptr); MALLOC(file_name, strlen(ptr = Shift(&cmd)) + strlen(name) + 2, char); strcat(strcat(strcpy(file_name, ptr), "/"), name); delay = (delay = atoi((ptr = Shift(&cmd)) ? ptr : "10")) ? delay : 10; ptr = (ptr = Shift(&cmd)) ? ptr : "0.04"; sscanf(ptr, "%lf", &deadband); deadbandticks = (int)(deadband * 65536.0); SpawnRet(pri_ret, ptcb->name); } StackClr(ptcb); ptr = VAPost(ptmlq, ptcb->pmsg, strcpy(BufNew(), "MLGetpML")); pml = *((pML *)ptr); BufDelete(ptr); pmlnode = GetMLNodeByName(pml, name); mlread = pmlnode->pmldriver->mlread; LOG = fopen(file_name, "a"); for ( init = 0, temp_min = LONG_MIN, temp_max = LONG_MAX, hist_idx = 0; ; ) { // Jump the queue. ptr = VAPost(ptmlq, ptcb->pmsg, strcat(strcpy(BufNew(), "MLDoNode "), pmlnode->name)); BufDelete(ptr); // Wait until our device comes around. EventPend(pmlnode->psem, 0); for (i = 0; i < 4; ++i) { if (0 > (mlread)(pml, pmlnode, (char *)0, 0, 0)) { MLPathCheck(pml); continue; } dtemp = temp[hist_idx] - pmlnode->dev.ds1820.temp; dtemp_abs = dtemp < 0 ? -dtemp : dtemp; if (dtemp_abs > deadbandticks) { dt = ((tv[hist_idx].tv_sec - pmlnode->tv.tv_sec) << 16) + (((tv[hist_idx].tv_usec - pmlnode->tv.tv_usec) << 8) / (1000000>>8)); dtemp_dt = (double)dtemp/(double)dt; hist_idx = (hist_idx + 1) & 7; temp[hist_idx] = pmlnode->dev.ds1820.temp; tv[hist_idx] = pmlnode->tv; if (init) { ptm = localtime((time_t *)&pmlnode->tv.tv_sec); VAPrintf(0, (VAPRINTF)vfprintf, LOG ,"%04d%02d%02d%02d%02d%02d %.3f\n" ,ptm->tm_year + 1900 ,ptm->tm_mon + 1 ,ptm->tm_mday ,ptm->tm_hour ,ptm->tm_min ,ptm->tm_sec ,dtemp_dt ); fflush(LOG); VAPrintf(0, (VAPRINTF)vfprintf, pexec->LOG ,"%04d%02d%02d%02d%02d%02d %8.3f %8.3f %7.4f %s\n" ,ptm->tm_year + 1900 ,ptm->tm_mon + 1 ,ptm->tm_mday ,ptm->tm_hour ,ptm->tm_min ,ptm->tm_sec ,pmlnode->dev.ds1820.temp / 65536.0 ,32.0 + ((1.8 / 65536.0) * pmlnode->dev.ds1820.temp) ,dtemp_dt ,name ); fflush(pexec->LOG); } } init++; break; } EventSched(ptmlmsg, 0); TaskDelaySec(delay); } } //=============================================================================