📄 stream5.c
字号:
/*
* stream 5.c
*
* SECS2 alarm functionality
*
* Code by David Lindauer, CIMple technologies
*
*/
#include "secs2.h"
#include <string.h>
extern SA_STRUC secs_alarmlist[];
extern int enquire_list[NUMBER_ENQUIRIES];
extern uint language;
extern BOOL communicating;
extern BOOL send_nothing;
/* Number of alarms */
static int number_alarms;
/* ALARM REPORT SEND,
* Note that this one is sent asynchronously from the equipment
*/
static void S5f1(void)
{
int i;
for (i=0; i<number_alarms; i++) {
if ((BOOL)(secs_alarmlist[i].alstate) != *secs_alarmlist[i].value) {
// Something has changed, register it
secs_alarmlist[i].alstate = (BYTE) *secs_alarmlist[i].value;
if (secs_alarmlist[i].enabled &&
(secs_alarmlist[i].alstate || secs_alarmlist[i].clearable)) {
int temp;
// Can't send alarm if disabled or just went off and is not clearable
// But if we are here we can send it, so lock out parsing responses
// from the host
Secs2LockSend();
// Initialize the send header for this stream and func
Secs2bInitheader(TRUE,TRUE,ST_ALARMS,SA_REPORT);
// Send the data as per the specs
IF_LIST(3);
IF_BINARY(1);
SB((BYTE)((secs_alarmlist[i].alstate ? 0x80 : 0x00)
+ secs_alarmlist[i].alcd));
IF_UWORD(1);
SW(i);
IF_ASCII(temp = MIN(40,strlen(secs_alarmlist[i].text[language])));
SA(secs_alarmlist[i].text[language],temp);
// Mark the data as sendable and release the lock
Secs2bFlagSent();
Secs2UnlockSend();
break;
}
}
}
}
/* ALARM REPORT ACKNOWLEDGE,
* Note this is required to be sent by the host in the specs.
* The SECS1 MRA routines will notify the host if he doesn't send it,
* Here we just peek at the values and send an error on bad format
* Picky, picky picky!
*/
static void S5f2(void)
{
send_nothing = TRUE;
if (FV(FM_BINARY) != 1)
Secs2BaddataError();
// If the following is non-zero there was an error, but we don't check
RB();
}
// Enable/disable alarm send
static void S5f3(void)
{
int i, pos, aled, alid;
BYTE retcode = ACKC5_ACCEPTED;
// Check the format
if ((pos = FV(FM_LIST)) != 2)
Secs2BaddataError();
if ((pos = FV(FM_BINARY)) != 1)
Secs2BaddataError();
aled = RB() & ALED_ENABLE;
if ((pos = FV(FM_UWORD)/2) == 0)
alid = -1;
else
if (pos == 1)
alid = RW();
else
Secs2BaddataError();
// BAD ALID
if (alid >= number_alarms)
// Error if invalid ALID
retcode = ACKC5_UNACCEPTED;
else
if (alid == -1)
// ALID had zero length, change all according to aled
for (i=0; i<number_alarms; i++)
if (aled)
secs_alarmlist[i].enabled = TRUE;
else
secs_alarmlist[i].enabled = FALSE;
else
// There was an ALED, change just that one
if (aled)
secs_alarmlist[alid].enabled = TRUE;
else
secs_alarmlist[alid].enabled = FALSE;
// Put out return code
IF_BINARY(1);
SB(retcode);
}
// List Alarms Request
static void S5f5(void)
{
int i,entries;
// Verify format and read in entries
entries = FV(FM_UWORD)/2;
if (entries > NUMBER_ENQUIRIES)
Secs2ToomuchdataError();
for (i=0; i<entries; i++)
enquire_list[i] = RW();
// If no request, send all
if (entries == 0) {
IF_LIST(number_alarms);
for (i=0; i<number_alarms; i++) {
int temp;
IF_LIST(3);
secs_alarmlist[i].alstate = (BYTE) *secs_alarmlist[i].value;
IF_BINARY(1);
SB((BYTE)((secs_alarmlist[i].alstate ? 0x80 : 0x00)
+ secs_alarmlist[i].alcd));
IF_UWORD(1);
SW(i);
IF_ASCII(temp = MIN(40,strlen(secs_alarmlist[i].text[language])));
SA(secs_alarmlist[i].text[language],temp);
}
}
else {
// Send data according to specs
IF_LIST(entries);
for (i=0; i<entries; i++) {
int temp,thisentry;
thisentry = enquire_list[i];
IF_LIST(3);
if (thisentry >= number_alarms) {
// Invalid request, send zero length data
IF_BINARY(0);
IF_UWORD(1);
SW(thisentry);
IF_ASCII(0);
}
else {
// Valid request, pull data from tables
secs_alarmlist[thisentry].alstate = (BYTE) *secs_alarmlist[thisentry].value;
IF_BINARY(1);
SB((BYTE)((secs_alarmlist[thisentry].alstate ? 0x80 : 0x00)
+ secs_alarmlist[thisentry].alcd));
IF_UWORD(1);
SW(thisentry);
IF_ASCII(temp = MIN(40,strlen(secs_alarmlist[thisentry].text[language])));
SA(secs_alarmlist[thisentry].text[language],temp);
}
}
}
}
// List enabled alarm request
static void S5f7(void)
{
int i,count=0;
// Make sure there is only a header
Secs2CheckHeaderOnly();
// Count number of alarms we will send
for (i=0; i< number_alarms; i++)
if (secs_alarmlist[i].enabled)
count++;
IF_LIST(count);
if (count)
for (i=0; i<number_alarms; i++)
if (secs_alarmlist[i].enabled) {
int temp;
// Register the state, now S5F1 will not send the alarm
secs_alarmlist[i].alstate = (BYTE) *secs_alarmlist[i].value;
// Send the data off according to the specs
IF_LIST(3);
IF_BINARY(1);
SB((BYTE)((secs_alarmlist[i].alstate ? 0x80 : 0x00)
+ secs_alarmlist[i].alcd));
IF_UWORD(1);
SW(i);
IF_ASCII(temp = MIN(40,strlen(secs_alarmlist[i].text[language])));
SA(secs_alarmlist[i].text[language],temp);
}
}
// List of all valid stream five functions
static PASSFUNC Stream5funcs[] = {
{ SA_ALMACK, S5f2 },
{ SA_ENABLE, S5f3 },
{ SA_REQUEST, S5f5 },
{ SA_LISTENABLED, S5f7 },
{ 0, 0 } };
/* Function handler dispatch */
void Stream5(int number)
{
Secs2FuncDispatch(number, Stream5funcs);
}
/* Stream 5 init routine
* Count the number of alarm specifiers
*/
void Stream5Init(BOOL power_up)
{
BOOL done = FALSE;
if (power_up) {
number_alarms = 0;
while (!done)
if (secs_alarmlist[++number_alarms].text == 0)
done = TRUE;
}
}
/*
* A seperate process to monitor changing alarm values and notify host
* dynamically
*/
void AlarmSendoff(void)
{
while(TRUE) {
Pause();
// IF establish communications is working we are communicating
if (communicating)
S5f1();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -