From ce5767775d2b66bd798cc4fde46dfa746ee30382 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 9 Jun 2022 15:30:52 +0300 Subject: [PATCH] Working version --- BTA_modbusmeteo/olddaemon/CAN/can4linux.h | 211 ++++ BTA_modbusmeteo/olddaemon/CAN/can_io.c | 548 ++++++++++ BTA_modbusmeteo/olddaemon/CAN/can_io.h | 30 + BTA_modbusmeteo/olddaemon/Makefile | 7 + BTA_modbusmeteo/olddaemon/bta_meteo_can.c | 309 ++++++ BTA_modbusmeteo/olddaemon/bta_shdata.h | 1143 +++++++++++++++++++++ 6 files changed, 2248 insertions(+) create mode 100644 BTA_modbusmeteo/olddaemon/CAN/can4linux.h create mode 100644 BTA_modbusmeteo/olddaemon/CAN/can_io.c create mode 100644 BTA_modbusmeteo/olddaemon/CAN/can_io.h create mode 100644 BTA_modbusmeteo/olddaemon/Makefile create mode 100644 BTA_modbusmeteo/olddaemon/bta_meteo_can.c create mode 100644 BTA_modbusmeteo/olddaemon/bta_shdata.h diff --git a/BTA_modbusmeteo/olddaemon/CAN/can4linux.h b/BTA_modbusmeteo/olddaemon/CAN/can4linux.h new file mode 100644 index 0000000..96e3427 --- /dev/null +++ b/BTA_modbusmeteo/olddaemon/CAN/can4linux.h @@ -0,0 +1,211 @@ +/* + * can4linux.h - can4linux CAN driver module + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2001 port GmbH Halle/Saale + *------------------------------------------------------------------ + * $Header: /z2/cvsroot/products/0530/software/can4linux/src/can4linux.h,v 1.5 2004/05/14 10:02:54 oe Exp $ + * + *-------------------------------------------------------------------------- + * + * + * modification history + * -------------------- + * $Log: can4linux.h,v $ + * Revision 1.5 2004/05/14 10:02:54 oe + * - started supporting CPC-Card + * - version number in can4linux.h available + * - only one structure type for Config_par_t Command_par_t + * - new ioctl command CMD_CLEARBUFFERS + * + * Revision 1.4 2003/08/27 17:49:04 oe + * - New CanStatusPar structure + * + * Revision 1.3 2002/08/20 05:57:22 oe + * - new write() handling, now not ovrwriting buffer content if buffer fill + * - ioctl() get status returns buffer information + * + * Revision 1.2 2002/08/08 17:50:46 oe + * - MSG_ERR_MASK extended + * + * Revision 1.1 2002/01/10 19:13:19 oe + * - application header file changed name can.h -> can4linux.h + * + * Revision 1.2 2001/09/14 14:58:09 oe + * first free release + * + * Revision 1.1.1.1 2001/06/11 18:30:54 oe + * minimal version can4linux embedded, compile time Konfigurierbar + * + * + * + * + *-------------------------------------------------------------------------- + */ + + +/** +* \file can.h +* \author Heinz-JЭrgen Oertel, port GmbH +* $Revision: 1.5 $ +* $Date: 2004/05/14 10:02:54 $ +* +* can4linux interface definitions +* +* +* +*/ + + +#ifndef __CAN_H +#define __CAN_H + + +#define CAN4LINUXVERSION 0x0301 /*(Version 3.1)*/ + +#ifndef __KERNEL__ +#include +#endif + /*---------- the can message structure */ + +#define CAN_MSG_LENGTH 8 /**< maximum length of a CAN frame */ + + +#define MSG_RTR (1<<0) /**< RTR Message */ +#define MSG_OVR (1<<1) /**< CAN controller Msg overflow error */ +#define MSG_EXT (1<<2) /**< extended message format */ +#define MSG_PASSIVE (1<<4) /**< controller in error passive */ +#define MSG_BUSOFF (1<<5) /**< controller Bus Off */ +#define MSG_ (1<<6) /**< */ +#define MSG_BOVR (1<<7) /**< receive/transmit buffer overflow */ +/** +* mask used for detecting CAN errors in the canmsg_t flags field +*/ +#define MSG_ERR_MASK (MSG_OVR + MSG_PASSIVE + MSG_BUSOFF + MSG_BOVR) + +/** +* The CAN message structure. +* Used for all data transfers between the application and the driver +* using read() or write(). +*/ +typedef struct { + /** flags, indicating or controlling special message properties */ + int flags; + int cob; /**< CAN object number, used in Full CAN */ + unsigned long id; /**< CAN message ID, 4 bytes */ + struct timeval timestamp; /**< time stamp for received messages */ + short int length; /**< number of bytes in the CAN message */ + unsigned char data[CAN_MSG_LENGTH]; /**< data, 0...8 bytes */ +} canmsg_t; + + + +/** +---------- IOCTL requests */ + +#define COMMAND 0 /**< IOCTL command request */ +#define CONFIG 1 /**< IOCTL configuration request */ +#define SEND 2 /**< IOCTL request */ +#define RECEIVE 3 /**< IOCTL request */ +#define CONFIGURERTR 4 /**< IOCTL request */ +#define STATUS 5 /**< IOCTL status request */ + +/*---------- CAN ioctl parameter types */ +/** + IOCTL Command request parameter structure */ +struct Command_par { + int cmd; /**< special driver command */ + int target; /**< special configuration target */ + unsigned long val1; /**< 1. parameter for the target */ + unsigned long val2; /**< 2. parameter for the target */ + int error; /**< return value */ + unsigned long retval; /**< return value */ +}; + + +typedef struct Command_par Command_par_t ; +/** + PSW made them all the same + IOCTL Configuration request parameter structure */ +typedef struct Command_par Config_par_t ; + + +/** + IOCTL generic CAN controller status request parameter structure */ +typedef struct CanStatusPar { + unsigned int baud; /**< actual bit rate */ + unsigned int status; /**< CAN controller status register */ + unsigned int error_warning_limit; /**< the error warning limit */ + unsigned int rx_errors; /**< content of RX error counter */ + unsigned int tx_errors; /**< content of TX error counter */ + unsigned int error_code; /**< content of error code register */ + unsigned int rx_buffer_size; /**< size of rx buffer */ + unsigned int rx_buffer_used; /**< number of messages */ + unsigned int tx_buffer_size; /**< size of tx buffer */ + unsigned int tx_buffer_used; /**< number of messages */ + unsigned long retval; /**< return value */ + unsigned int type; /**< CAN controller / driver type */ +} CanStatusPar_t; + +/** + IOCTL CanStatusPar.type CAN controller hardware chips */ +#define CAN_TYPE_UNSPEC 0 +#define CAN_TYPE_SJA1000 1 +#define CAN_TYPE_FlexCAN 2 +#define CAN_TYPE_TouCAN 3 +#define CAN_TYPE_82527 4 +#define CAN_TYPE_TwinCAN 5 + + +/** + IOCTL Send request parameter structure */ +typedef struct Send_par { + canmsg_t *Tx; /**< CAN message struct */ + int error; /**< return value for errno */ + unsigned long retval; /**< return value */ +} Send_par_t ; + +/** + IOCTL Receive request parameter structure */ +typedef struct Receive_par { + canmsg_t *Rx; /**< CAN message struct */ + int error; /**< return value for errno */ + unsigned long retval; /**< return value */ +} Receive_par_t ; + +/** +IOCTL ConfigureRTR request parameter structure */ +typedef struct ConfigureRTR_par { + unsigned message; /**< CAN message ID */ + canmsg_t *Tx; /**< CAN message struct */ + int error; /**< return value for errno */ + unsigned long retval; /**< return value */ +} ConfigureRTR_par_t ; + +/** +---------- IOCTL Command subcommands and there targets */ + +# define CMD_START 1 +# define CMD_STOP 2 +# define CMD_RESET 3 +# define CMD_CLEARBUFFERS 4 + + + + +/** +---------- IOCTL Configure targets */ + +# define CONF_ACC 0 /* mask and code */ +# define CONF_ACCM 1 /* mask only */ +# define CONF_ACCC 2 /* code only */ +# define CONF_TIMING 3 /* bit timing */ +# define CONF_OMODE 4 /* output control register */ +# define CONF_FILTER 5 +# define CONF_FENABLE 6 +# define CONF_FDISABLE 7 + +#endif /* __CAN_H */ diff --git a/BTA_modbusmeteo/olddaemon/CAN/can_io.c b/BTA_modbusmeteo/olddaemon/CAN/can_io.c new file mode 100644 index 0000000..db10660 --- /dev/null +++ b/BTA_modbusmeteo/olddaemon/CAN/can_io.c @@ -0,0 +1,548 @@ +/* CAN I/O library (to use as a process) + * usage: + * first: fork() + start_can_io(NULL) - start CAN Rx-buffering process + * then: fork() + Control_1(....) - start process that uses recv/send functions + * ........................... + * then: fork() + Control_N(....) + * + * note: use init_can_io() at the begining of every Control process + * BUT DON't USE it in main() before Control process start + * ^^^^^^^^^^^^^ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "can4linux.h" +#include "can_io.h" + +char can_dev[40] = "/dev/can0"; +int can_fd=-1; +char can_lck[40] = "/tmp/dev_can0.lock"; +int can_lk=-1; +static int server_mode=0; +static int my_uid; + +#define CAN_SHM_SIZE ((sizeof(int)*3)+CAN_CTLR_SIZE+(CAN_RX_SIZE*sizeof(canmsg_t))) + +union ShMkey { + char name[5]; + key_t code; +} can_shm_key; +int can_shm_id=-1; +char *can_shm_addr = NULL; +#define can_pid (*(((int *)can_shm_addr)+0)) /* PID of CAN I/O process */ +#define can_open (*(((int *)can_shm_addr)+1)) /* file descr.of CAN-driver */ +#define rx_buff_pntr (*(((int *)can_shm_addr)+2)) /* from 0 till CAN_RX_SIZE-1 */ +void *can_ctrl_addr = NULL; /* shm area reserved for control process purpose*/ +canmsg_t *rx_buff; /* rx ring buffer: CAN_RX_SIZE*sizeof(canmsg_t)*/ + +struct CMD_Queue { /* описание очереди (канала) команд */ + union { + char name[5]; /* ключ идентефикации очереди */ + key_t code; + } key; + int mode; /* режим доступа (rwxrwxrwx) */ + int side; /* тип подсоединения: Клиент/Сервер (Sender/Receiver)*/ + int id; /* дескриптор подсоединения */ + unsigned int acckey; /* ключ доступа (для передачи Клиент->Сервер) */ +}; +/* канал команд используем для передачи CAN-фреймов */ +static struct CMD_Queue canout = {{'C','A','N',0,0},0200,0,-1,0}; + +/* структура сообщения */ +struct my_msgbuf { + long mtype; /* type of message */ + unsigned long acckey; /* ключ доступа клиента */ + unsigned long src_pid; /* номер процесса источника */ + unsigned long src_ip; /* IP-адр. источника, =0 - локальная команда */ + char mtext[100]; /* message text */ +}; + +static void can_abort(int sig); + +void set_server_mode(int mode) {server_mode=mode;} +int can_server() {return(server_mode);} +int can_card() {return(can_fd>0);} +int can_gate() {return(0);} +double can_gate_time_offset() {return(0.0);} + +void setup_can_net(unsigned long ipaddr, int port, unsigned long acckey) {return;} +unsigned long get_acckey() {return(0);} + +static int shm_created=0; + +/* to use _AFTER_ process forking */ +void *init_can_io() { /* returns shared area addr. for client control process*/ + int i,ret; + int new_shm=0; + char *p, msg[100]; + + my_uid=geteuid(); + if(can_shm_addr==NULL) { + if((p=strrchr(can_dev,'/'))!=NULL) { + memcpy(&can_lck[9], p+1, 4); + memcpy(can_shm_key.name, p+1, 4); + can_shm_key.name[4]='\0'; + } else { + fprintf(stderr,"Wrong CAN device name: %s\n", can_dev); + exit(1); + } + can_shm_id = shmget(can_shm_key.code, CAN_SHM_SIZE, 0644); + if(can_shm_id<0 && errno==EACCES) + can_shm_id = shmget(can_shm_key.code, CAN_SHM_SIZE, 0444); + if(can_shm_id<0 && errno==ENOENT && server_mode) { + can_shm_id = shmget(can_shm_key.code, CAN_SHM_SIZE, IPC_CREAT|IPC_EXCL|0644); + new_shm = shm_created = 1; + } + if(can_shm_id<0) { + can_prtime(stderr); + if(new_shm) + sprintf(msg,"Can't create shm CAN buffer '%s'",can_shm_key.name); + else if(server_mode) + sprintf(msg,"CAN-I/O: Can't find shm segment for CAN buffer '%s'",can_shm_key.name); + else + sprintf(msg,"Can't find shm segment for CAN buffer '%s' (maybe no CAN-I/O process?)",can_shm_key.name); + perror(msg); + exit(errno); + } + can_shm_addr = shmat(can_shm_id, NULL, 0); + if ((int)(can_shm_addr) == -1 && errno==EACCES) + can_shm_addr = shmat(can_shm_id, NULL, SHM_RDONLY); + if ((int)(can_shm_addr) == -1) { + sprintf(msg,"Can't attach shm CAN buffer '%s'",can_shm_key.name); + perror(msg); + ret=shmctl(can_shm_id, IPC_RMID, NULL); + exit(errno); + } + } + can_ctrl_addr = (canmsg_t *)(can_shm_addr+sizeof(int)*3); + rx_buff = (canmsg_t *)(can_ctrl_addr+CAN_CTLR_SIZE); + + if(can_fd<0 && canout.id<0) { + if(server_mode) { + if(( can_fd = open(can_dev, O_RDWR )) < 0 ) { + sprintf(msg,"CAN-I/O: Error opening CAN device %s", can_dev); + can_prtime(stderr); + perror(msg); + ret=shmctl(can_shm_id, IPC_RMID, NULL); + exit(errno); + } + } else { + if((canout.id = msgget(canout.key.code, canout.mode)) < 0) { + sprintf(msg,"Error opening CAN output queue '%s'(maybe no CANqueue server process?) ",canout.key.name); + perror(msg); + } + } + } + if(can_lk>0) close(can_lk); + if(( can_lk = open(can_lck, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH )) < 0 ) { + sprintf(msg,"Error opening CAN device lock-file %s", can_lck); + perror(msg); + ret=shmctl(can_shm_id, IPC_RMID, NULL); + close(can_fd); + exit(errno); + } + fchmod(can_lk, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if(new_shm) { + struct timeval tmv; + struct timezone tz; + gettimeofday(&tmv,&tz); + if(flock(can_lk, LOCK_EX)<0) perror("locking CAN"); + can_pid = 0; + can_open = -1; + rx_buff_pntr = 0; + for(i=0; i 0) { + /* work around the timestamp bug in old driver version */ + while((double)rx.timestamp.tv_sec+(double)rx.timestamp.tv_usec/1e6 < (double)tm.tv_sec+(double)tm.tv_usec/1e6) { + rx.timestamp.tv_usec += 10000; + if(rx.timestamp.tv_usec > 1000000) { + rx.timestamp.tv_sec++; + rx.timestamp.tv_usec -= 1000000; + } + } + if(flock(can_lk, LOCK_EX)<0) perror("locking CAN"); + rx_buff[rx_buff_pntr] = rx; + rx_buff_pntr = (rx_buff_pntr + 1) % CAN_RX_SIZE; + if(flock(can_lk, LOCK_UN)<0) perror("unlocking CAN"); +//fprintf(stderr,"%d read(id=%02x,len=%d)\n",rx_buff_pntr,rx.id,rx.length);fflush(stderr); + /*fprintf(stderr,"reading CAN: 1 frame\n");*/ + } else { + fprintf(stderr,"reading CAN: nothing\n");fflush(stderr); + } +// } while(n>0); + } +} + +/* put CAN-frame to recv-buffer */ +void can_put_buff_frame(double rtime, int id, int length, unsigned char data[]) { + int i; + canmsg_t rx; + int sec = (int)rtime; + if(!server_mode) return; + if(length<0) length=0; + if(length>8) length=8; + rx.id=id; + rx.length=length; + for(i=0; i0 && can_open>0); +} + + +/* Все нормально с CAN-I/O процессом */ +/* (но надо быть супер-юзером!) */ +int can_io_ok() { + return(can_io_shm_ok() && (my_uid!=0||kill(can_pid, 0)==0)); +} + + +/* Возможна работа c CAN для клиента */ +int can_ok() { + return(can_io_shm_ok()); +} + + +/* wait for CAN-frame */ +int can_wait(int fd, double tout) +{ + int nfd,width; + struct timeval tv; + fd_set readfds; + + if(fd==0 && tout>=0.01) { + double dt = can_dsleep(tout); + if(dt>0.) can_dsleep(dt); + return(0); + } + if(fd<0) fd=can_fd; + if(fd>0) { + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + width = fd+1; + } else + width = 0; + tv.tv_sec = (int)tout; + tv.tv_usec = (int)((tout - tv.tv_sec)*1000000.+0.9); +slipping: + if(fd>0 && can_fd>0) + nfd = select(width, &readfds, (fd_set *)NULL, (fd_set *)NULL, &tv); + else + nfd = select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &tv); + if(nfd < 0) { + if(errno == EINTR) + goto slipping; + perror("Error in can_wait(){ select() }"); + return(-1); + } else if(nfd == 0) /* timeout! */ + return(0); + if(fd>0 && FD_ISSET(fd, &readfds)) /* Rx frame! */ + return(1); + return(0); +} + +/* cleanup recv-buffer in client process */ +void can_clean_recv(int *pbuf, double *rtime) { + struct timeval tmv; + struct timezone tz; + gettimeofday(&tmv,&tz); + *pbuf = rx_buff_pntr; + *rtime = tmv.tv_sec + (double)tmv.tv_usec/1000000.; +} + +/* find next rx-frame in recv-buffer for client process */ +int can_recv_frame(int *pbuf, double *rtime, + int *id, int *length, unsigned char data[]) { + return(can_get_buff_frame(pbuf, rtime, id, length, data)); +} +int can_get_buff_frame(int *pbuf, double *rtime, + int *id, int *length, unsigned char data[]) { + while(*pbuf != rx_buff_pntr) { + canmsg_t *rx = &rx_buff[*pbuf]; + struct timeval *tv = &rx->timestamp; + double t_rx; + + if(flock(can_lk, LOCK_EX)<0) perror("locking CAN"); + + t_rx = tv->tv_sec + (double)tv->tv_usec/1000000.; + if(t_rx+1. >= *rtime) { + int i; + *id = rx->id; + *length = rx->length; + for(i = 0; i < *length; i++) + data[i] = rx->data[i]; + *rtime = t_rx; + *pbuf = (*pbuf + 1) % CAN_RX_SIZE; + + if(flock(can_lk, LOCK_UN)<0) perror("unlocking CAN"); + return(1); + } + *pbuf = (*pbuf + 1) % CAN_RX_SIZE; + + if(flock(can_lk, LOCK_UN)<0) perror("unlocking CAN"); + } + return(0); +} + +/* send tx-frame from client process */ +/* to CAN-driver or to output queue */ +int can_send_frame(int id, int length, unsigned char data[]) { + int i, ret=1; + if(can_fd<0 && canout.id<0) + return(0); + if(length>8) length=8; + if(length<0) length=0; + if(can_fd>=0) { + canmsg_t tx; + tx.id=id; + tx.cob=0; + tx.flags=0; + tx.length=length; + for(i=0;i=0) { + struct my_msgbuf mbuf; + mbuf.src_pid = getpid(); + mbuf.src_ip = 0; + mbuf.acckey = canout.acckey; + mbuf.mtype = id; + for(i=0;i=0) close(can_fd); + can_prtime(stderr); + fprintf(stderr,"%s process stop!\n",ss); + fflush(stderr); + close(can_lk); + ret=shmdt(can_shm_addr); + ret=shmctl(can_shm_id, IPC_STAT, &buf); + if(buf.shm_nattch==0) + ret=shmctl(can_shm_id, IPC_RMID, NULL); + exit(sig); + } +} + +char *time2asc(double t) +{ + static char stmp[10][20]; + static int itmp=0; + char *lin = stmp[itmp]; + int h, min; + double sec; + h = (int)(t/3600.); + min = (int)((t - (double)h*3600.)/60.); + sec = t - (double)h*3600. - (double)min*60.; + h %= 24; + sprintf(lin, "%02d:%02d:%09.6f", h,min,sec); + itmp = (itmp+1)%10; + return lin; +} + +double can_dsleep(double dt) { + struct timespec ts,tsr; + ts.tv_sec = (time_t)dt; + ts.tv_nsec = (long)((dt-ts.tv_sec)*1e9); + nanosleep(&ts,&tsr); + return((double)ts.tv_sec + (double)ts.tv_nsec/1e9); +} + +double can_dtime() { + struct timeval ct; + struct timezone tz; + gettimeofday(&ct, &tz); + return ((double)ct.tv_sec + (double)ct.tv_usec/1e6); +} + +char *can_atime() {return(time2asc(can_dtime()));} + +void can_prtime(FILE *fd) { + static double otime=0.0; + double ntime=can_dtime(); + time_t itime = (int)ntime; + if(otime==0.0) tzset(); + ntime -= (double)timezone; + if((((int)ntime)%(24*3600) < ((int)otime)%(24*3600)) || otime==0.0) + fprintf(fd,"========================\n%s",ctime(&itime)); + fprintf(fd,"%s ",time2asc(ntime)); + otime=ntime; +} diff --git a/BTA_modbusmeteo/olddaemon/CAN/can_io.h b/BTA_modbusmeteo/olddaemon/CAN/can_io.h new file mode 100644 index 0000000..5c49254 --- /dev/null +++ b/BTA_modbusmeteo/olddaemon/CAN/can_io.h @@ -0,0 +1,30 @@ +#define CAN_CTLR_SIZE 300 /* size of client process shared area */ +#define CAN_RX_SIZE 1000 /* max. # frames in Rx-buffer */ + +int can_wait(int fd, double tout); +#define can_delay(Tout) can_wait(0, Tout) +void set_server_mode(int mode); +int can_server(); +int can_card(); +int can_gate(); +double can_gate_time_offset(); +void setup_can_net(unsigned long ipaddr, int port, unsigned long acckey); +unsigned long get_acckey(); +void *init_can_io(); +void *start_can_io(void *arg); +void can_put_buff_frame(double rtime, int id, int length, unsigned char data[]); +int can_io_ok(); +int can_io_shm_ok(); +int can_ok(); +void can_clean_recv(int *pbuf, double *rtime); +int can_get_buff_frame(int *pbuf, double *rtime, + int *id, int *length, unsigned char data[]); +int can_recv_frame(int *pbuf, double *rtime, + int *id, int *length, unsigned char data[]); +int can_send_frame(int id, int length, unsigned char data[]); +void can_exit(int sig); +char *time2asc(double t); +double can_dsleep(double dt); +double can_dtime(); +char *can_atime(); +void can_prtime(FILE *fd); diff --git a/BTA_modbusmeteo/olddaemon/Makefile b/BTA_modbusmeteo/olddaemon/Makefile new file mode 100644 index 0000000..3584af7 --- /dev/null +++ b/BTA_modbusmeteo/olddaemon/Makefile @@ -0,0 +1,7 @@ +CFLAGS=-g + +bta_meteo_can: bta_meteo_can.c bta_shdata.h CAN/can_io.h CAN/can_io.o + cc -g bta_meteo_can.c CAN/can_io.o -lcrypt -o bta_meteo_can +# setroot bta_meteo_can + +CAN/can_io.o: CAN/can_io.c CAN/can_io.h CAN/can4linux.h diff --git a/BTA_modbusmeteo/olddaemon/bta_meteo_can.c b/BTA_modbusmeteo/olddaemon/bta_meteo_can.c new file mode 100644 index 0000000..b723e4c --- /dev/null +++ b/BTA_modbusmeteo/olddaemon/bta_meteo_can.c @@ -0,0 +1,309 @@ +/* Получение метео-данных от PEP-контроллеров по CAN-шине */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bta_shdata.h" +#include "CAN/can_io.h" + +const double zeroV = 1.0; +const double scaleT = 50.0/(5.-1.); /* New: 1:5V -> -20:+30dgr */ +const double zeroT2 = -19.1; /* -20.0 + 0.9 Tind (16.11.2012)*/ + +static int stop_prog = 0; +static char *myname; + +static void print_date(FILE *fdout) { + static char lastdate[40] = "01.01.2000 00:00:00"; + const char *formdate = "%d.%m.%Y %H:%M:%S"; + time_t t; + struct tm *tm; + char currdate[40]; + int len; + + time(&t); + tm = localtime(&t); + len = strftime(currdate,40,formdate,tm); + if(strncmp(lastdate,currdate,11)==0) + fprintf(fdout,"%s ", &currdate[11]); + else + fprintf(fdout,"Date: %s ", currdate); + + strncpy(lastdate,currdate,20); +} + +static void fprtime(FILE *fd) { can_prtime(fd); } + +static double dsleep(double dt) { + struct timespec ts,tsr; + ts.tv_sec = (time_t)dt; + ts.tv_nsec = (long)((dt-ts.tv_sec)*1e9); + nanosleep(&ts,&tsr); + return((double)ts.tv_sec + (double)ts.tv_nsec/1e9); +} + +static double dtime() { + struct timeval ct; + struct timezone tz; + gettimeofday(&ct, &tz); + return (ct.tv_sec + ct.tv_usec/1e6); +} + +static void myabort(int sig) { + int ret; + char ss[10], tmp[80]; + signal(sig,SIG_IGN); + switch (sig) { + case SIGHUP : strcpy(ss,"SIGHUP"); break; + case SIGINT : strcpy(ss,"SIGINT"); break; + case SIGQUIT: strcpy(ss,"SIGQUIT"); break; + case SIGFPE : strcpy(ss,"SIGFPE"); break; + case SIGPIPE: strcpy(ss,"SIGPIPE"); break; + case SIGSEGV: strcpy(ss,"SIGSEGV"); break; + case SIGTERM: strcpy(ss,"SIGTERM"); break; + default: sprintf(ss,"SIG_%d",sig); break; + } + print_date(stderr); + switch (sig) { + default: + + case SIGHUP : + case SIGINT : + fprintf(stderr,"%s: %s - Ignore .....\n",myname,ss); + fflush(stderr); + signal(sig, myabort); + return; + case SIGPIPE: + case SIGQUIT: + case SIGFPE : + case SIGSEGV: + case SIGTERM: + signal(SIGALRM, SIG_IGN); + fprintf(stderr,"%s: %s - programm stop!\n",myname,ss); + fflush(stderr); + stop_prog = sig; + return; + } +} + +static int rxpnt; +static double rxtime; + +int main (int argc, char *argv[]) +{ + double tcurr, tlast, tok, twndok; + char msg[60]; + double t0=0., t; + int i,m,n, idr, idt, dlen, start=0, imsg; + unsigned char rdata[8],tdata[8]; + char tmp[100],tmp1[100], pmsg[48], *pmsgp; + + myname = argv[0]; + tzset(); + print_date(stderr); + sdat.mode |= 0200; + sdat.atflag = 0; + get_shm_block( &sdat, ClientSide); + get_cmd_queue( &ocmd, ClientSide); + + MeteoMode &= ~SENSOR_T2; + + init_can_io(); + can_clean_recv(&rxpnt, &rxtime); + fprintf(stderr,"\n"); + + signal(SIGHUP, myabort); + signal(SIGINT, myabort); + signal(SIGQUIT,myabort); + signal(SIGFPE, myabort); + signal(SIGPIPE,myabort); + signal(SIGSEGV,myabort); + signal(SIGTERM,myabort); + + imsg=0; + pmsgp=pmsg; + + t0 = tcurr = tlast = tok = twndok = dtime(); + tok -= 600.; + + while (1) { + char *pep = "RK"; + int nch = 0; + dsleep(0.2); + tcurr = dtime(); + if(PEP_A_On && PEP_R_On) { + if(!stop_prog && !start && tcurr-tok>15.) { + idt = 0x447; + dlen=6; + tdata[0] = 7; + tdata[2] = 50; /* 0.5s */ + tdata[3] = 1; + tdata[4] = 0; tdata[5] = 50; /* 0.5s */ + for(i=0; i<8; i++) { + if(i==2||i==3||i==5||i==6) /* T-зеркала, ветер, влажность, T на метео-мачте */ + continue; /* пока не используются (заменены) */ + if(i==4) { /*временно: пока АЦП4 идет с PEP-A (давление)*/ + pep = "A"; + idt = 0x40f; /* PEP-A */ + tdata[1] = nch = 4; /* АЦП/4 */ + } else { + pep = "RK"; + idt = 0x447; /* PEP-RK */ + tdata[1] = nch = i; /* АЦП/i */ + } + print_date(stderr); + if(can_send_frame(idt, dlen, tdata)<=0) { + fprintf(stderr,"Can't send command \"Start ADC%d\" to PEP-%s!\n",nch,pep); + } else if(tcurr-tlast<70.) + fprintf(stderr,"Send command \"Start ADC%d\" to PEP-%s.\n",nch,pep); + fflush(stderr); + } + start=1; + tok = tcurr; + } + if(stop_prog || (start && tcurr-tok>5.)) { + if(!stop_prog) { + print_date(stderr); + fprintf(stderr,"PEP-RK: ADC(0,1,7) (or PEP-A ADC4) timeout!\n"); + } +#if 0 + MeteoMode &= ~SENSOR_T2; + idt = 0x447; + dlen=6; + tdata[0] = 7; + tdata[2] = tdata[3] = tdata[4] = tdata[5] = 0; + for(i=0; i<8; i++) { + if(i==2||i==3||i==5||i==6) /* T-зеркала, ветер, влажность, T на метео-мачте */ + continue; /* пока не используются (заменены) */ + if(i==4) { /*временно: пока АЦП4 идет с PEP-A (давление)*/ + pep = "A"; + idt = 0x40f; /* PEP-A */ + tdata[1] = nch = 4; /* АЦП/4 */ + } else { + pep = "RK"; + idt = 0x447; /* PEP-RK */ + tdata[1] = nch = i; /* АЦП/i */ + } + print_date(stderr); + if(can_send_frame(idt, dlen, tdata)<=0) { + fprintf(stderr,"Can't send command \"Stop ADC%d\" to PEP-%s!\n",nch,pep); + } else if(tcurr-tlast<70.) + fprintf(stderr,"Send command \"Stop ADC%d\" to PEP-%s.\n",nch,pep); + fflush(stderr); + } +#endif + if(stop_prog) can_exit(0); + start=0; + tok = tcurr; + } + } else { + if(stop_prog) can_exit(0); + else { + static int tpr = 0; + if(tcurr-tpr>600.) { + if(PEP_R_Off) { + print_date(stderr); + fprintf(stderr,"PEP-RK (ADC0/1/7) turned off!\n"); + } + if(PEP_A_Off) { + print_date(stderr); + fprintf(stderr,"PEP-A (ADC4) turned off!\n"); + } + tpr=tcurr; + } + if(PEP_R_Off) { + if((MeteoMode & NET_T2)==0) + MeteoMode &= ~SENSOR_T2; + } + } + } + while(can_recv_frame(&rxpnt, &rxtime, &idr, &dlen, rdata)) { + int rcode = 0; + t = rxtime; + if(idr==0x447||idr==0x40f) { + pep = (idr==0x40f)? "A" : "RK"; + if(rdata[0]==7) { + if(rdata[2] == 0 && rdata[3] == 0) + fprintf(stderr,"%s PEP-%s: Echo command \"Stop ADC%d\"\n", time2asc(rxtime-timezone),pep,rdata[1]); + else + fprintf(stderr,"%s PEP-%s: Echo command \"Start ADC%d\"\n", time2asc(rxtime-timezone),pep,rdata[1]); + } else if(rdata[0]==8) { + fprintf(stderr,"%s PEP-%s: Echo command \"Stop all ADC\"\n", time2asc(rxtime-timezone),pep); + start=0; + } + fflush(stderr); + } else if(idr==0x20c) { /* временно: код АЦП4 PEP-A - давление */ + if(dlen!=3) + goto wrong_frame; + idr = 0x224; /* временно: имитация АЦП4 PEP-RK */ + goto adc_pep_rk; + } else if((idr&0xff8)==0x220) { /* код от АЦП PEP-RK */ + static double T2 = 0.; + static int ctm=0; + static int terr=0; + int chan, code; + double volt,T,b,w,h; + adc_pep_rk: + if(dlen!=3) { + static double last_print = 0.; + wrong_frame: + if(tcurr-last_print > 60.) { + print_date(stderr); + fprintf(stderr,"Wrong CAN-frame id=0x%x len=%d < ",idr,dlen); + for(i=0; i\n"); + fflush(stderr); + last_print = tcurr; + } + continue; + } + chan = idr&7; + code = (unsigned int)rdata[0]<<8|rdata[1]; + volt = (double)code/4096.*5.; /* ADC 12bit 0-5V */ + if(chan == 1){ /* АЦП1 - T-подкупольного */ + ctm |= 2; /* АЦП1 - T-подкупольного */ + T = zeroT2 + (volt-zeroV)*scaleT; + /*t2=T;*/ + if(T >= -20. && T <= 30.) { + if((MeteoMode & SENSOR_T2) && fabs(T2-T)<5.) { + if(fabs(T2-T)>0.1) + T2 += (T2>T)? -0.005 : 0.005; + else + T2 = 0.9*T2 + 0.1*T; + } else { + T2=T; + MeteoMode |= SENSOR_T2; + } + } else { + terr |= 2; + if(T<-20.) T2=-20.; + else if(T>30.) T2=30.; + MeteoMode &= ~SENSOR_T2; + } + if((MeteoMode & INPUT_T2)== 0 && (MeteoMode & SENSOR_T2)) + val_T2 = T2; +//printf("Get T=%.1f\n", T2); + tok = t; + } + if(chan<3 && (ctm&0x93) == 0x93) { /* АЦП-0,1,4,7 - Ok */ + tok = t; + ctm=0; + } + tlast=t; + } + fflush(stdout); + } + if(stop_prog) can_exit(0); + } +} diff --git a/BTA_modbusmeteo/olddaemon/bta_shdata.h b/BTA_modbusmeteo/olddaemon/bta_shdata.h new file mode 100644 index 0000000..fffc110 --- /dev/null +++ b/BTA_modbusmeteo/olddaemon/bta_shdata.h @@ -0,0 +1,1143 @@ + +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ + +#include +#include +#include + +struct SHM_Block { /* описание блока разделяемой памяти */ + union { + char name[5]; /* ключ идентефикации сегмента памяти */ + key_t code; + } key; + int size; /* размер используемой части в байтах */ + int maxsize; /* размер при создании ("с запасом" для будущих версий) */ + int mode; /* режим доступа (rwxrwxrwx) */ + int atflag; /* режим подсоединения (SHM_RDONLY или 0) */ + void (*init)(); /* процедура инициализации */ + int (*check)(); /* процедура проверки */ + void (*close)(); /* процедура отсоединения */ + int side; /* тип подсоединения: Клиент/Сервер */ + int id; /* дескриптор подсоединения */ + unsigned char *addr; /* адрес подсоединения */ +}; + +struct CMD_Queue { /* описание очереди (канала) команд */ + union { + char name[5]; /* ключ идентефикации очереди */ + key_t code; + } key; + int mode; /* режим доступа (rwxrwxrwx) */ + int side; /* тип подсоединения: Клиент/Сервер (Sender/Receiver)*/ + int id; /* дескриптор подсоединения */ + unsigned int acckey; /* ключ доступа (для передачи Клиент->Сервер) */ +}; + +#ifndef BTA_MODULE +/* канал команд главного операторского интерфейса (Level5)*/ +struct CMD_Queue mcmd = {{'M','c','m','d',0},0200,0,-1,0}; +/* канал передачи операторских (привелегированных) команд (Level4)*/ +struct CMD_Queue ocmd = {{'O','c','m','d',0},0200,0,-1,0}; +/* канал передачи пользовательских (непривелегированных) команд (Level2/3)*/ +struct CMD_Queue ucmd = {{'U','c','m','d',0},0200,0,-1,0}; +#else +extern struct CMD_Queue mcmd; +extern struct CMD_Queue ocmd; +extern struct CMD_Queue ucmd; +#endif + +extern char *crypt(const char *key, const char *salt); + +static void send_cmd_noarg(int); +static void send_cmd_str(int, char *); +static void send_cmd_i1(int, int); +static void send_cmd_i2(int, int, int); +static void send_cmd_i3(int, int, int, int); +static void send_cmd_i4(int, int, int, int, int); +static void send_cmd_d1(int, double); +static void send_cmd_d2(int, double, double); +static void send_cmd_i1d1(int, int, double); +static void send_cmd_i2d1(int, int, int, double); +static void send_cmd_i3d1(int, int, int, int, double); + +/* список команд */ +/* имя код аргументы тип */ +#define StopTel 1 /* останов телескопа */ +#define StopTeleskope() send_cmd_noarg( 1 ) /* опер. */ +#define StartHS 2 /* старт привода наведения */ +#define StartHightSpeed() send_cmd_noarg( 2 ) /* опер/тст*/ +#define StartLS 3 /* старт привода ведения */ +#define StartLowSpeed() send_cmd_noarg( 3 ) /* опер/тст*/ +#define SetTmr 4 /* уст. Ch7_15 или SysTimer */ +#define SetTimerMode(T) send_cmd_i1 ( 4, (int)(T)) /* М.опер. */ +#define SetModMod 5 /* уст. режим моделирования */ +#define SetModelMode(M) send_cmd_i1 ( 5, (int)(M)) /* М.опер. */ +#define SetCodA 6 /* код скорости по A */ +#define SetPKN_A(iA,sA) send_cmd_i2 ( 6, (int)(iA),(int)(sA)) /* опер/тст*/ +#define SetCodZ 7 /* код скорости по Z */ +#define SetPKN_Z(iZ) send_cmd_i1 ( 7, (int)(iZ)) /* опер/тст*/ +#define SetCodP 8 /* код скорости по P */ +#define SetPKN_P(iP) send_cmd_i1 ( 8, (int)(iP)) /* опер/тст*/ +#define SetVA 9 /* уст. скорость по A */ +#define SetSpeedA(vA) send_cmd_d1 ( 9, (double)(vA)) /* опер/тст*/ +#define SetVZ 10 /* уст. скорость по Z */ +#define SetSpeedZ(vZ) send_cmd_d1 (10, (double)(vZ)) /* опер/тст*/ +#define SetVP 11 /* уст. скорость по P */ +#define SetSpeedP(vP) send_cmd_d1 (11, (double)(vP)) /* опер/тст*/ +#define SetAD 12 /* зап.новые координаты R.A.и Decl */ +#define SetRADec(Alp,Del) send_cmd_d2 (12, (double)(Alp),(double)(Del))/* польз.*/ +#define SetAZ 13 /* зап.координаты азимут и зен.расст.*/ +#define SetAzimZ(A,Z) send_cmd_d2 (13, (double)(A),(double)(Z))/* польз.*/ +#define GoToAD 14 /* старт наведения на объект (по R.A.и Decl)*/ +#define GoToObject() send_cmd_noarg(14 ) /* опер. */ +#define MoveToAD 15 /* переезд на объект (по R.A.и Decl)*/ +#define MoveToObject() send_cmd_noarg(15 ) /* польз.*/ +#define GoToAZ 16 /* наведение по положению (по A Z)*/ +#define GoToAzimZ() send_cmd_noarg(16 ) /* опер. */ +#define WriteAZ 17 /* установка A и Z для FullModel*/ +#define WriteModelAZ() send_cmd_noarg(17 ) /* опер. */ +#define SetModP 18 /* уст. режим использования P2 */ +#define SetPMode(pmod) send_cmd_i1 (18, (int)(pmod)) /* польз.*/ +#define P2Move 19 /* вкл./выкл. (+-1,0) движение P2 */ +#define MoveP2(dir) send_cmd_i1 (19, (int)(dir)) /* польз.*/ +#define FocMove 20 /* вкл./выкл. (+-2,+-1,0) движение фокуса */ +#define MoveFocus(speed,time) send_cmd_i1d1(20,(int)(speed),(double)(time)) /* польз.*/ +#define UsePCorr 21 /* режим учета поправок положения (СКН) */ +#define SwitchPosCorr(pc_flag) send_cmd_i1 (21, (int)(pc_flag)) /* опер. */ +#define SetTrkFlags 22 /* уст. флагов режима слежения */ +#define SetTrkOkMode(trk_flags) send_cmd_i1 (22, (int)(trk_flags)) /* опер.*/ +#define SetTFoc 23 /* уст.фокуса: 0-ПФ, 1-Н1, 2-Н2 */ +#define SetTelFocus(N) send_cmd_i1 ( 23, (int)(N)) /* опер. */ +#define SetVAD 24 /* уст.ск.собсв.дв-я объекта по R.A.и Decl */ +#define SetVelAD(VAlp,VDel) send_cmd_d2 (24, (double)(VAlp),(double)(VDel))/* опер.*/ +#define SetRevA 25 /* уст. режим "обхода" азимута */ +#define SetAzRevers(amod) send_cmd_i1 (25, (int)(amod)) /* польз.*/ +#define SetVP2 26 /* уст.скор..дв-я P2 (для ДБУ) */ +#define SetVelP2(vP2) send_cmd_d1 (26, (double)(vP2)) /* польз.*/ +#define SetTarg 27 /* уст. цели наведения */ +#define SetSysTarg(Targ) send_cmd_i1 (27, (int)(Targ)) /* опер.*/ +#define SendMsg 28 /* размещение сообщения (всем клиентам и в протокол) */ +#define SendMessage(Mesg) send_cmd_str (28, (char *)(Mesg)) /* польз.*/ +#define CorrAD 29 /* коррекция координат R.A.и Decl */ +#define DoADcorr(dAlp,dDel) send_cmd_d2 (29, (double)(dAlp),(double)(dDel))/* польз.*/ +#define CorrAZ 30 /* коррекция координат A и Z*/ +#define DoAZcorr(dA,dZ) send_cmd_d2 (30, (double)(dA),(double)(dZ))/* польз.*/ +#define SetVCAZ 31 /* уст.скор.коррекции по A и Z*/ +#define SetVCorr(vA,vZ) send_cmd_d2 (31, (double)(vA),(double)(vZ))/* польз.*/ +#define P2MoveTo 32 /* переезд P2 по времени */ +#define MoveP2To(vP2,time) send_cmd_d2 (32, (double)(vP2),(double)(time))/* польз.*/ +#define GoToTD 33 /* старт наведения на стационар (по t и Decl)*/ +#define GoToSat() send_cmd_noarg (33 ) /* опер..*/ +#define MoveToTD 34 /* переезд на стационар (по t и Decl)*/ +#define MoveToSat() send_cmd_noarg (34 ) /* польз.*/ +#define NullCom 35 /* пустая команда (для синхронизаций?) */ +#define SyncCom() send_cmd_noarg (35 ) /* опер. */ +#define StartTel 36 /* кнопка "Пуск" телескопа */ +#define StartTeleskope() send_cmd_noarg(36 ) /* опер. */ +#define SetTMod 37 /* уст. режимы работы телескопа */ +#define SetTelMode(M) send_cmd_i1 ( 37, (int)(M)) /* М.опер. */ +#define TelOn 38 /* кнопка Вкл. Масло, ЭМУ и т.д.*/ +#define TeleskopeOn() send_cmd_noarg(38 ) /* М.опер. */ +#define SetModD 39 /* уст. режим использования купола */ +#define SetDomeMode(dmod) send_cmd_i1 (39, (int)(dmod)) /* М.опер.*/ +#define DomeMove 40 /* вкл./выкл. (+-1+-2,+-3,0) движение купола */ +#define MoveDome(speed,time) send_cmd_i1d1(40,(int)(speed),(double)(time)) /* опер.*/ +#define SetPass 41 /* уст. пароль уровня доступа */ +#define SetPasswd(LPass) send_cmd_str (41, (char *)(LPass)) /* М.опер.*/ +#define SetLevC 42 /* уст. код уровня доступа */ +#define SetLevCode(Nlev,Cod) send_cmd_i2(42, (int)(Nlev),(int)(Cod)) /* М.опер.*/ +#define SetLevK 43 /* уст. ключ уровня доступа */ +#define SetLevKey(Nlev,Key) send_cmd_i2(43, (int)(Nlev),(int)(Key)) /* М.опер.*/ +#define SetNet 44 /* уст. маску и адрес подсети */ +#define SetNetAcc(Mask,Addr) send_cmd_i2(44, (int)(Mask),(int)(Addr)) /* М.опер.*/ +#define SetMet 45 /* ввод метео данных */ +#define SetMeteo(m_id,m_val) send_cmd_i1d1(45,(int)(m_id),(double)(m_val)) /* опер.*/ +#define TurnMetOff 46 /* отмена исп. метео данных */ +#define TurnMeteoOff(m_id) send_cmd_i1 (46, (int)(m_id)) /* опер.*/ +#define SetDUT1 47 /* уст.попр.времени(IERS DUT1=UT1-UTC) */ +#define SetDtime(dT) send_cmd_d1 (47, (double)(dT)) /* М.опер.*/ +#define SetPM 48 /* уст.полож.полюса(IERS polar motion)*/ +#define SetPolMot(Xp,Yp) send_cmd_d2 (48, (double)(Xp),(double)(Yp)) /* М.опер.*/ +#define GetSEW 49 /* прочитать SEW параметр */ +#define GetSEWparam(Ndrv,Indx,Cnt) send_cmd_i3(49,(int)(Ndrv),(int)(Indx),(int)(Cnt)) /* M.опер.*/ +#define PutSEW 50 /* записать SEW параметр */ +#define PutSEWparam(Ndrv,Indx,Key,Val) send_cmd_i4(50,(int)(Ndrv),(int)(Indx),(int)(Key),(int)(Val)) /* M.опер.*/ +#define SetLocks 51 /* установка блокировок управления узлами */ +#define SetLockFlags(f) send_cmd_i1 (SetLocks, (int)(f)) /* M.опер.*/ +#define ClearLocks 52 /* отмена блокировок управления узлами */ +#define ClearLockFlags(f) send_cmd_i1 (ClearLocks, (int)(f)) /* M.опер.*/ +#define SetRKbits 53 /* Установка доп.битов PEP-RK */ +#define AddRKbits(f) send_cmd_i1 (SetRKbits, (int)(f)) /* M.опер.*/ +#define ClrRKbits 54 /* Очистка доп.битов PEP-RK */ +#define ClearRKbits(f) send_cmd_i1 (ClrRKbits, (int)(f)) /* M.опер.*/ +#define SetSEWnd 55 /* уст.номер SEW-движка купола (для индикации)*/ +#define SetDomeDrive(ND) send_cmd_i1 (SetSEWnd, (int)(ND)) /* М.опер.*/ +#define SEWsDome 56 /* Вкл./Выкл. SEW-движков купола */ +#define DomeSEW(OnOff) send_cmd_i1 (SEWsDome, (int)(OnOff)) /* М.опер.*/ + + +/* структура данных алгоритма управления (распределение "глобальной области") */ +#define BTA_Data_Ver 2 +#pragma pack(push,4) +struct BTA_Data { + int magic; /* код опознания структуры */ + int version; /* номер версии структуры = BTA_Data_Ver*/ + int size; /* размер структуры = sizeof(struct BTA_Data)*/ + int pid; +#define ServPID (sdt->pid) /*номер процесса гл.упр.программы */ + + /* режимы работы */ + int model; +#define UseModel (sdt->model) /* вариант использования моделирования */ +#define NoModel 0 /* отключено */ +#define CheckModel 1 /* привода контролируются по модели */ +#define DriveModel 2 /* моделирование приводов и "слепое" управление без реальных датчиков */ +#define FullModel 3 /* полное моделирование без телескопа */ + int timer; +#define ClockType (sdt->timer) /* какие часы используются */ +#define Ch7_15 0 /* Внутр.часы упр.программы с синхронизацией по Ч7-15 */ +#define SysTimer 1 /* Таймер системы (неизвестно синхронизированный или нет) */ +#define ExtSynchro 2 /* Работает синхронизация таймера системы внешней программой (bta_time или xntpd)*/ + int system; +#define Sys_Mode (sdt->system) /* режим работы системы */ +#define SysStop 0 /* Останов */ +#define SysWait 1 /* Ожидание старта (наведения) */ +#define SysPointAZ 2 /* Наведение по положению (по A Z)*/ +#define SysPointAD 3 /* Наведение на объект (по R.A.и Decl)*/ +#define SysTrkStop 4 /* Ведение: ожидание старта */ +#define SysTrkStart 5 /* Ведение: разгон до номин.скорости (объекта)*/ +#define SysTrkMove 6 /* Ведение: переезд на объект */ +#define SysTrkSeek 7 /* Ведение: слежение за объектом */ +#define SysTrkOk 8 /* Ведение: рассогласования в допуске */ +#define SysTrkCorr 9 /* Ведение: коррекция положения */ +#define SysTest 10 /* Тестирование */ + int sys_target; +#define Sys_Target (sdt->sys_target) /* цель наведения */ +#define TagPosition 0 /* Положение A/Z */ +#define TagObject 1 /* Объект Alpha/Delta */ +#define TagNest 2 /* Положение "Гнездо" */ +#define TagZenith 3 /* Положение "Зенит" */ +#define TagHorizon 4 /* Положение "Горизонт" */ +#define TagStatObj 5 /* "Стационар" t/Delta */ + + int tel_focus; +#define Tel_Focus (sdt->tel_focus) /* тип фокуса телескопа: 0-ПФ, 1-Н1, 2-Н2 */ +#define Prime 0 +#define Nasmyth1 1 +#define Nasmyth2 2 + double pc_coeff[8]; +#define PosCor_Coeff (sdt->pc_coeff) /* коэф-ты СКН для тек.фокуса */ + + /* состояние телескопа */ +#define Stopping 0 /* Останов */ +#define Pointing 1 /* Наведение */ +#define Tracking 2 /* Ведение */ + int tel_state; +#define Tel_State (sdt->tel_state) /* реально отрабатываемое */ + int req_state; +#define Req_State (sdt->req_state) /* затребованное программой */ + int tel_hard_state; +#define Tel_Hardware (sdt->tel_hard_state) /* состояние УСО */ +#define Hard_Off 0 /* питание выключено */ +#define Hard_On 1 /* включено */ + + /* режимы работы телескопа */ + int tel_mode; +#define Tel_Mode (sdt->tel_mode) +#define Automatic 0 /* "Автомат" - нормальный режим*/ +#define Manual 1 /* "П/авт.упр." - пультовой режим и в нем:*/ +#define ZenHor 2 /* "Зенит-Горизонт" - работа при Z<5 и Z>80*/ +#define A_Move 4 /* ручное движение A */ +#define Z_Move 8 /* --- "" --- Z */ +#define Balance 0x10 /* балансировка трубы */ + + /* вкл./выкл. режим "обхода" азимута */ + int az_mode; +#define Az_Mode (sdt->az_mode) +#define Rev_Off 0 /* нормальное наведение на ближайшее положение по азимуту */ +#define Rev_On 1 /* наведение с перегоном на 360град. */ + + /* работа P2 */ + int p2_state; +#define P2_State (sdt->p2_state) /* реальное состояние привода P2 */ +#define P2_Off 0 /* Стоит */ +#define P2_On 1 /* Ведет */ +#define P2_Plus 2 /* быстро едет в + */ +#define P2_Minus -2 /* быстро едет в - */ + int p2_req_mode; +#define P2_Mode (sdt->p2_req_mode) /* режим использования P2 (пока: Вкл/Выкл)*/ + + /* состояние привода фокуса */ + int focus_state; +#define Foc_State (sdt->focus_state) +#define Foc_Off 0 /* Стоит */ +#define Foc_Lplus 1 /* медл. едет в + */ +#define Foc_Lminus -1 /* медл. едет в - */ +#define Foc_Hplus 2 /* быстро едет в + */ +#define Foc_Hminus -2 /* быстро едет в - */ + + /* состояние привода купола */ + int dome_state; +#define Dome_State (sdt->dome_state) +#define D_On 7 /* Автоматическое согласование с телескопом */ +#define D_Off 0 /* Стоит */ +#define D_Lplus 1 /* медл. едет в + */ +#define D_Lminus -1 /* медл. едет в - */ +#define D_Mplus 2 /* сред.скор. в + */ +#define D_Mminus -2 /* сред.скор. в - */ +#define D_Hplus 3 /* быстро едет в + */ +#define D_Hminus -3 /* быстро едет в - */ + +/* учет поправок положения (СКН) */ + int pcor_mode; +#define Pos_Corr (sdt->pcor_mode) /* коррекция положения объекта по A/Z: Вкл/Выкл*/ +#define PC_Off 0 /* Выкл. */ +#define PC_On 1 /* Вкл. */ + +/* флаги вкл/выкл. вариантов режима слежения */ + int trkok_mode; +#define TrkOk_Mode (sdt->trkok_mode) +#define UseDiffVel 1 /* определение&учет поправок реальной скорости приводов (~изодором)*/ +#define UseDiffAZ 2 /* слежение по рассогласованию (иначе уст.рассчетн.скоростей) */ +#define UseDFlt 4 /* вкл. цифрового фильтра рассогласований */ + + /* введенные значения */ + double i_alpha, i_delta; +#define InpAlpha (sdt->i_alpha) /* введенная координата R.A. (sec) */ +#define InpDelta (sdt->i_delta) /* -- " -- Decl. (") */ + double s_alpha, s_delta; +#define SrcAlpha (sdt->s_alpha) /* исходная координата R.A. (sec) */ +#define SrcDelta (sdt->s_delta) /* -- " -- Decl. (") */ + double v_alpha, v_delta; +#define VelAlpha (sdt->v_alpha) /* ск.собсв.дв-я объекта по R.A. (sec/сек) */ +#define VelDelta (sdt->v_delta) /* -- " -- Decl. ("/сек) */ + double i_azim, i_zdist; +#define InpAzim (sdt->i_azim) /* для наведения по азимуту (") */ +#define InpZdist (sdt->i_zdist) /* -- " -- зен.расст. (") */ + + /* рассчетные значения */ + double c_alpha, c_delta; +#define CurAlpha (sdt->c_alpha) /* текущая координата R.A. (sec) */ +#define CurDelta (sdt->c_delta) /* -- " -- Decl. (") */ + double tag_a, tag_z, tag_p; +#define tag_A (sdt->tag_a) /* текущий A (") объекта */ +#define tag_Z (sdt->tag_z) /* - " - Z (") - " - */ +#define tag_P (sdt->tag_p) /* - " - P (") - " - */ + double pcor_a, pcor_z, refr_z; +#define pos_cor_A (sdt->pcor_a) /* поправка положения объекта по A (") */ +#define pos_cor_Z (sdt->pcor_z) /* - " - - " - по Z (") */ +#define refract_Z (sdt->refr_z) /* поправка за рефракцию для объекта (") */ + double tcor_a, tcor_z, tref_z; +#define tel_cor_A (sdt->tcor_a) /* поправка обр.пересчета положения телескопа по A (") */ +#define tel_cor_Z (sdt->tcor_z) /* - " - - " - - " - по Z (") */ +#define tel_ref_Z (sdt->tref_z) /* поправка обр.пересчета за рефракцию (") */ + double diff_a, diff_z, diff_p; +#define Diff_A (sdt->diff_a) /* рассогл-е(осталось ехать) по A (") */ +#define Diff_Z (sdt->diff_z) /* - " - - " - Z (") */ +#define Diff_P (sdt->diff_p) /* - " - - " - P (") */ + double vbasea,vbasez,vbasep; +#define vel_objA (sdt->vbasea) /* базовая скорость объекта по A ("/сек) */ +#define vel_objZ (sdt->vbasez) /* - " - - " - Z - " - */ +#define vel_objP (sdt->vbasep) /* - " - - " - P - " - */ + double diffva,diffvz,diffvp; +#define diff_vA (sdt->diffva) /* поправка реальной скорости привода по азимуту */ +#define diff_vZ (sdt->diffvz) /* -- "" -- -- "" -- по Z */ +#define diff_vP (sdt->diffvp) /* -- "" -- -- "" -- по P */ + double speeda,speedz,speedp; +#define speedA (sdt->speeda) /* скорость по A ("/сек) для управления приводом */ +#define speedZ (sdt->speedz) /* - " - Z - " - */ +#define speedP (sdt->speedp) /* - " - P - " - */ + double m_time_precip; +#define Precip_time (sdt->m_time_precip)/* момент времени появления осадков (precipitations)*/ + unsigned char reserve[16]; +#define Reserve (sdt->reserve) /* свободное место */ + double rspeeda, rspeedz, rspeedp; +#define req_speedA (sdt->rspeeda) /* скорость ("/сек) выданная на привод A */ +#define req_speedZ (sdt->rspeedz) /* - " - Z */ +#define req_speedP (sdt->rspeedp) /* - " - P */ + double simvela, simvelz, simvelp, simvelf, simveld; +#define mod_vel_A (sdt->simvela) /* скорость по A ("/сек) модельная */ +#define mod_vel_Z (sdt->simvelz) /* - " - Z - " - */ +#define mod_vel_P (sdt->simvelp) /* - " - P - " - */ +#define mod_vel_F (sdt->simvelf) /* - " - F - " - */ +#define mod_vel_D (sdt->simvelf) /* - " - D - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + unsigned int kost; +#define code_KOST (sdt->kost) /* сост. телескопа и ручной коррекции */ + /* 0x8000 - азимут положительный */ + /* 0x4000 - отработка вкл. */ + /* 0x2000 - режим ведения */ + /* 0x1000 - отработка P2 вкл.*/ + /* 0x01F0 - ск.корр. 0.2 0.4 1.0 2.0 5.0("/сек) */ + /* 0x000F - напр.корр. +Z -Z +A -A */ + double m_time, s_time, l_time; +#define M_time (sdt->m_time) /* текущее московское время (теперь UTC!)*/ +#define S_time (sdt->s_time) /* текущее звездное время */ +#define L_time (sdt->l_time) /* время работы программы */ + unsigned int ppndd_a, ppndd_z, ppndd_p, ppndd_b; +#define ppndd_A (sdt->ppndd_a) /* код датчика ППНДД (грубого отсчета) A */ +#define ppndd_Z (sdt->ppndd_z) /* - "" - Z */ +#define ppndd_P (sdt->ppndd_p) /* - "" - P */ +#define ppndd_B (sdt->ppndd_b) /* код датчика ППНДД давления */ + unsigned int dup_a, dup_z, dup_p, dup_f, dup_d; +#define dup_A (sdt->dup_a) /* код Грея датчика ДУП (точного отсчета) A */ +#define dup_Z (sdt->dup_z) /* - "" - Z */ +#define dup_P (sdt->dup_p) /* - "" - P */ +#define dup_F (sdt->dup_f) /* код Грея датчика ДУП фокуса телескопа */ +#define dup_D (sdt->dup_d) /* код Грея датчика ДУП положения купола */ + unsigned int low_a, low_z, low_p, low_f, low_d; +#define low_A (sdt->low_a) /* 14р-в дв.кода точного отсчета A */ +#define low_Z (sdt->low_z) /* - "" - Z */ +#define low_P (sdt->low_p) /* - "" - P */ +#define low_F (sdt->low_f) /* код отсчета фокуса телескопа */ +#define low_D (sdt->low_d) /* код отсчета положения купола */ + unsigned int code_a, code_z, code_p, code_b, code_f, code_d; +#define code_A (sdt->code_a) /* 23р-в дв.кода отсчета A */ +#define code_Z (sdt->code_z) /* - "" - Z */ +#define code_P (sdt->code_p) /* - "" - P */ +#define code_B (sdt->code_b) /* код давления */ +#define code_F (sdt->code_f) /* код отсчета фокуса телескопа */ +#define code_D (sdt->code_d) /* код отсчета положения купола */ + unsigned int adc[8]; +#define ADC(N) (sdt->adc[(N)]) /* коды 8-ми каналов АЦП PCL818 */ +#define code_T1 ADC(0) /* код датчика наруж. температуры*/ +#define code_T2 ADC(1) /* код датчика температуры под куп.*/ +#define code_T3 ADC(2) /* код датчика температуры зеркала */ +#define code_Wnd ADC(3) /* код датчика ветра */ + double val_a, val_z, val_p, val_b, val_f, val_d; + double val_t1, val_t2, val_t3, val_wnd; +#define val_A (sdt->val_a) /* отсчет A (") */ +#define val_Z (sdt->val_z) /* - " - Z (") */ +#define val_P (sdt->val_p) /* - " - P (") */ +#define val_B (sdt->val_b) /* давлениe (мм.рт.ст.)*/ +#define val_F (sdt->val_f) /* фокус телескопа (мм) */ +#define val_D (sdt->val_d) /* положение купола (") */ +#define val_T1 (sdt->val_t1) /* наруж. температура (гр.)*/ +#define val_T2 (sdt->val_t2) /* температура под куп.(гр.)*/ +#define val_T3 (sdt->val_t3) /* температура зеркала (гр.)*/ +#define val_Wnd (sdt->val_wnd) /* ветер (м/сек)*/ + double val_alp, val_del; +#define val_Alp (sdt->val_alp) /* обратный пересчет R.A. (sec) */ +#define val_Del (sdt->val_del) /* -- " -- Decl. (") */ + + double vel_a, vel_z, vel_p, vel_f, vel_d; +#define vel_A (sdt->vel_a) /* скорость по A ("/сек) измеренная */ +#define vel_Z (sdt->vel_z) /* - " - Z - " - */ +#define vel_P (sdt->vel_p) /* - " - P - " - */ +#define vel_F (sdt->vel_f) /* - " - F - " - */ +#define vel_D (sdt->vel_d) /* - " - D - " - */ + + /* очередь последних системных сообщений */ +#define MesgNum 3 +#define MesgLen 39 + struct SysMesg { + int seq_num; + char type; +#define MesgEmpty 0 +#define MesgInfor 1 +#define MesgWarn 2 +#define MesgFault 3 +#define MesgLog 4 + char text[MesgLen]; + } sys_msg_buf[MesgNum]; +#define Sys_Mesg(N) (sdt->sys_msg_buf[N]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + unsigned int code_lev1,code_lev2,code_lev3,code_lev4,code_lev5; +#define code_Lev1 (sdt->code_lev1) /* "удаленный наблюдатель" - только информация */ +#define code_Lev2 (sdt->code_lev2) /* "местный наблюдатель" - + ввод координат */ +#define code_Lev3 (sdt->code_lev3) /* "главный наблюдатель" - + A/Z-корр-я, упр.P2/F */ +#define code_Lev4 (sdt->code_lev4) /* "оператор" - + пуск/стоп телеск., тестирование */ +#define code_Lev5 (sdt->code_lev5) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + unsigned int netmask, netaddr, acsmask, acsaddr; +#define NetMask (sdt->netmask) /* маска подсети (обычно: 255.255.255.0) */ +#define NetWork (sdt->netaddr) /* адрес подсети (например: 192.168.3.0) */ +#define ACSMask (sdt->acsmask) /* маска АСУ-сети (например: 255.255.255.0) */ +#define ACSNet (sdt->acsaddr) /* адрес АСУ-сети (например: 192.168.13.0) */ + + /* ввод метео-данных */ + int meteo_stat; +#define MeteoMode (sdt->meteo_stat) /* флаги датчиков и ввода данных*/ +#define INPUT_B 1 /* давление *//* флаги ручного ввода метео данных */ +#define INPUT_T1 2 /* T-наружная */ +#define INPUT_T2 4 /* T-подкупольная */ +#define INPUT_T3 8 /* T-зеркала */ +#define INPUT_WND 0x10 /* ветер */ +#define INPUT_HMD 0x20 /* влажность */ +#define SENSOR_B (INPUT_B <<8) /* флаги внешних метео-датчиков (e.g.по CAN-шине)*/ +#define SENSOR_T1 (INPUT_T1 <<8) +#define SENSOR_T2 (INPUT_T2 <<8) +#define SENSOR_T3 (INPUT_T3 <<8) +#define SENSOR_WND (INPUT_WND<<8) +#define SENSOR_HMD (INPUT_HMD<<8) +#define ADC_B (INPUT_B <<16) /* флаги считывания с АЦП упр.компутера */ +#define ADC_T1 (INPUT_T1 <<16) +#define ADC_T2 (INPUT_T2 <<16) +#define ADC_T3 (INPUT_T3 <<16) +#define ADC_WND (INPUT_WND<<16) +#define ADC_HMD (INPUT_HMD<<16) +#define NET_B (INPUT_B <<24) /* флаги получения данных с метеостанции по сети */ +#define NET_T1 (INPUT_T1 <<24) +#define NET_T2 (INPUT_T2 <<24) +#define NET_T3 (INPUT_T3 <<24) +#define NET_WND (INPUT_WND<<24) +#define NET_HMD (INPUT_HMD<<24) + double inp_b, inp_t1, inp_t2, inp_t3, inp_wnd; +#define inp_B (sdt->inp_b) /* давлениe (мм.рт.ст.)*/ +#define inp_T1 (sdt->inp_t1) /* наруж. температура (гр.)*/ +#define inp_T2 (sdt->inp_t2) /* температура под куп.(гр.)*/ +#define inp_T3 (sdt->inp_t3) /* температура зеркала (гр.)*/ +#define inp_Wnd (sdt->inp_wnd) /* ветер (м/сек)*/ + + double temper, press; +#define Temper (sdt->temper) /* темрература используемая для рефракции */ +#define Pressure (sdt->press) /* давление используемое для рефракции */ + double m_time10, m_time15; +#define Wnd10_time (sdt->m_time10) /* момент времени порыва >=10м/сек*/ +#define Wnd15_time (sdt->m_time15) /* - " - - " - - " - >=15м/сек*/ + + /* IERS DUT1 (источник: ftp://maia.usno.navy.mil/ser7/ser7.dat) */ + double dut1; +#define DUT1 (sdt->dut1) /* поправка ср.солнечного времени: DUT1 = UT1-UTC */ + + double a_time, z_time, p_time; +#define A_time (sdt->a_time) /* момент считывания датчика A */ +#define Z_time (sdt->z_time) /* - " - - " - - " - Z */ +#define P_time (sdt->p_time) /* - " - - " - - " - P */ + + double speedain, speedzin, speedpin; +#define speedAin (sdt->speedain) /* постоянная скорость уст-я по A */ +#define speedZin (sdt->speedzin) /* постоянная скорость уст-я по Z */ +#define speedPin (sdt->speedpin) /* постоянная скорость уст-я по P2*/ + + double acc_a, acc_z, acc_p, acc_f, acc_d; +#define acc_A (sdt->acc_a) /* ускорение по A ("/сек^2) */ +#define acc_Z (sdt->acc_z) /* - " - Z - " - */ +#define acc_P (sdt->acc_p) /* - " - P - " - */ +#define acc_F (sdt->acc_f) /* - " - F - " - */ +#define acc_D (sdt->acc_d) /* - " - D - " - */ + + unsigned int code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + unsigned int l; + } value; +} sewdrv[3]; +#define statusSEW(Drv) (sdt->sewdrv[(Drv)-1].status) /*состояние контроллера*/ +#define statusSEW1 (sdt->sewdrv[0].status) +#define statusSEW2 (sdt->sewdrv[1].status) +#define statusSEW3 (sdt->sewdrv[2].status) +#define speedSEW(Drv) (sdt->sewdrv[(Drv)-1].set_speed) /*установленная скорость*/ +#define speedSEW1 (sdt->sewdrv[0].set_speed) /* об/мин (rpm)*/ +#define speedSEW2 (sdt->sewdrv[1].set_speed) +#define speedSEW3 (sdt->sewdrv[2].set_speed) +#define vel_SEW(Drv) (sdt->sewdrv[(Drv)-1].mes_speed) /*измеренная скорость */ +#define vel_SEW1 (sdt->sewdrv[0].mes_speed) /* об/мин (rpm)*/ +#define vel_SEW2 (sdt->sewdrv[1].mes_speed) +#define vel_SEW3 (sdt->sewdrv[2].mes_speed) +#define currentSEW(Drv) (sdt->sewdrv[(Drv)-1].current) /*ток (А)*/ +#define currentSEW1 (sdt->sewdrv[0].current) +#define currentSEW2 (sdt->sewdrv[1].current) +#define currentSEW3 (sdt->sewdrv[2].current) +#define indexSEW(Drv) (sdt->sewdrv[(Drv)-1].index) /*номер параметра*/ +#define indexSEW1 (sdt->sewdrv[0].index) +#define indexSEW2 (sdt->sewdrv[1].index) +#define indexSEW3 (sdt->sewdrv[2].index) +#define valueSEW(Drv) (sdt->sewdrv[(Drv)-1].value.l) /*код значения параметра*/ +#define valueSEW1 (sdt->sewdrv[0].value.l) +#define valueSEW2 (sdt->sewdrv[1].value.l) +#define valueSEW3 (sdt->sewdrv[2].value.l) +#define bvalSEW(Drv,Nb) (sdt->sewdrv[(Drv)-1].value.b[Nb]) /*байт кода значения параметра*/ + +/* информация от PEP-контроллеров */ + unsigned int pep_code_a, pep_code_z, pep_code_p; +#define PEP_code_A (sdt->pep_code_a) /* 23р-в дв.кода отсчета A */ +#define PEP_code_Z (sdt->pep_code_z) /* - "" - Z */ +#define PEP_code_P (sdt->pep_code_p) /* - "" - P */ + unsigned int pep_sw_a, pep_sw_z, pep_sw_p; +#define switch_A (sdt->pep_sw_a) /* код концевиков азимута */ +#define Sw_minus_A 1 /* азимут отрицательный (см. code_KOST&0x8000)*/ +#define Sw_plus240_A 2 /* концевик "+240град" */ +#define Sw_minus240_A 4 /* концевик "-240град" */ +#define Sw_minus45_A 8 /* положение "в горизонт" (~-46град)*/ +#define switch_Z (sdt->pep_sw_z) /* код концевиков Z */ +#define Sw_0_Z 0x01 /* концевик "0град" */ +#define Sw_5_Z 0x02 /* концевик "5град" */ +#define Sw_20_Z 0x04 /* концевик "20град" */ +#define Sw_60_Z 0x08 /* концевик "60град" */ +#define Sw_80_Z 0x10 /* концевик "80град" */ +#define Sw_90_Z 0x20 /* концевик "90град" */ +#define switch_P (sdt->pep_sw_p) /* - "" - СПФ */ +#define Sw_No_P 0x00 /* "Нет концевиков" */ +#define Sw_22_P 0x01 /* концевик "22град" */ +#define Sw_89_P 0x02 /* концевик "89град" */ +#define Sw_Sm_P 0x80 /* датчик дыма СПФ */ + unsigned int pep_code_f, pep_code_d, pep_code_ri, pep_code_ro; +#define PEP_code_F (sdt->pep_code_f) /* код отсчета фокуса телескопа */ +#define PEP_code_D (sdt->pep_code_d) /* код отсчета положения купола */ +#define PEP_code_Rin (sdt->pep_code_ri)/* код принятый из РК */ +#define PEP_code_Rout (sdt->pep_code_ro)/* код выдаваемый в РК */ + unsigned char pep_on[10]; /* флаги работы PEP-контроллеров */ +#define PEP_A_On (sdt->pep_on[0]) +#define PEP_A_Off (PEP_A_On==0) +#define PEP_Z_On (sdt->pep_on[1]) +#define PEP_Z_Off (PEP_Z_On==0) +#define PEP_P_On (sdt->pep_on[2]) +#define PEP_P_Off (PEP_P_On==0) +#define PEP_F_On (sdt->pep_on[3]) +#define PEP_F_Off (PEP_F_On==0) +#define PEP_D_On (sdt->pep_on[4]) +#define PEP_D_Off (PEP_D_On==0) +#define PEP_R_On (sdt->pep_on[5]) +#define PEP_R_Off ((PEP_R_On&1)==0) +#define PEP_R_Inp ((PEP_R_On&2)!=0) +#define PEP_K_On (sdt->pep_on[6]) +#define PEP_K_Off ((PEP_K_On&1)==0) +#define PEP_K_Inp ((PEP_K_On&2)!=0) + + /* IERS polar motion (источник: ftp://maia.usno.navy.mil/ser7/ser7.dat) */ + double xpol, ypol; +#define polarX (sdt->xpol) /* X-поправкa полож.полюса */ +#define polarY (sdt->ypol) /* Y-поправкa полож.полюса */ + + double jdate, eetime; +#define JDate (sdt->jdate) /* текущая юлианская дата */ +#define EE_time (sdt->eetime) /* поправ.зв.вр. за "Equation of the Equinoxes" */ + + /* еще ввод метео-данных */ + double val_hmd, inp_hmd; +#define val_Hmd (sdt->val_hmd) /* значение влажности (%) */ +#define inp_Hmd (sdt->val_hmd) /* ручной ввод */ + + /* положение червяка (подвеска) */ + double worm_a, worm_z; +#define worm_A (sdt->worm_a) /* положение подвески A (мкм) */ +#define worm_Z (sdt->worm_z) /* положение подвески Z (мкм) */ + + /* флаги блокировки управления узлами */ + unsigned int lock_flags; +#define LockFlags (sdt->lock_flags) +#define Lock_A 0x01 +#define Lock_Z 0x02 +#define Lock_P 0x04 +#define Lock_F 0x08 +#define Lock_D 0x10 +#define A_Locked (LockFlags&Lock_A) +#define Z_Locked (LockFlags&Lock_Z) +#define P_Locked (LockFlags&Lock_P) +#define F_Locked (LockFlags&Lock_F) +#define D_Locked (LockFlags&Lock_D) + + /* требуемая скорость привода купола (для упр-я SEW-приводами)*/ + int sew_dome_speed; /* пока тоже что и Dome_State */ +#define Dome_Speed (sdt->sew_dome_speed) /* т.е. D_Lplus,D_Lminus,.... */ + +/* номер SEW-движка купола (для индикации)*/ + int sew_dome_num; +#define DomeSEW_N (sdt->sew_dome_num) + +/* параметры выбранного(DomeSEW_N) SEW-контроллера купола*/ +struct SEWdata sewdomedrv; +#define statusSEWD (sdt->sewdomedrv.status) /*состояние контроллера*/ +#define speedSEWD (sdt->sewdomedrv.set_speed) /*установленная скорость об/мин (rpm)*/ +#define vel_SEWD (sdt->sewdomedrv.mes_speed) /*измеренная скорость об/мин (rpm)*/ +#define currentSEWD (sdt->sewdomedrv.current) /*ток (А)*/ +#define indexSEWD (sdt->sewdomedrv.index) /*номер параметра*/ +#define valueSEWD (sdt->sewdomedrv.value.l) /*код значения параметра*/ + +/* информация PEP-контроллера купола */ + unsigned int pep_code_di, pep_code_do; +#define PEP_code_Din (sdt->pep_code_di) /* код принятый из PEP-купола */ +#define PEP_Dome_SEW_Ok 0x200 +#define PEP_Dome_Cable_Ok 0x100 +#define PEP_code_Dout (sdt->pep_code_do) /* код выдаваемый в PEP-купола */ +#define PEP_Dome_SEW_On 0x10 +#define PEP_Dome_SEW_Off 0x20 + +}; +#pragma pack(pop) + +#ifndef BTA_MODULE +struct BTA_Data *sdt; +#else +extern struct BTA_Data *sdt; +#endif + +struct BTA_Local { /* структура локальных данных */ + unsigned char reserve[120]; /* свободное место для расширения глобальной области */ + /* (на глобальную область резервируем 1500 байт) */ + double pr_oil_a,pr_oil_z,pr_oil_t; +#define PressOilA (sdtl->pr_oil_a) /* Давление в маслопроводе A (МПа) */ +#define PressOilZ (sdtl->pr_oil_z) /* Давление в маслопроводе Z (МПа) */ +#define PressOilTank (sdtl->pr_oil_t) /* Датчик уровня масла в баке(КПа) */ + double t_oil_1,t_oil_2; +#define OilTemper1 (sdtl->t_oil_1) /* Температура масла */ +#define OilTemper2 (sdtl->t_oil_2) /* Температура охлаждающей воды */ +}; + +#ifndef BTA_MODULE +struct BTA_Local *sdtl; /* конец глобальных, начало локальных данных */ +#else +extern struct BTA_Local *sdtl; +#endif + +#define ClientSide 0 +#define ServerSide 1 + +#ifndef BTA_MODULE +static void bta_data_init(); +static int bta_data_check(); +static void bta_data_close(); + +/* описание блока данных алгоритма управления ("глобальная область") */ +struct SHM_Block sdat = { +{'S','d','a','t',0},sizeof(struct BTA_Data),2048,0444,SHM_RDONLY,bta_data_init,bta_data_check,bta_data_close,0,-1,NULL +}; +#else +extern struct SHM_Block sdat; +#endif + +#ifndef BTA_MODULE +/* инициализация данных алгоритма управления (обнуление "глобальной области") */ +static void bta_data_init() { + int i; + sdt = (struct BTA_Data *)sdat.addr; + sdtl = (struct BTA_Local *)(sdat.addr+sizeof(struct BTA_Data)); + if(sdat.side == ClientSide) { + if(sdt->magic != sdat.key.code) { + fprintf(stderr,"Wrong shared data (maybe server turned off)\n"); + /*exit(1);*/ + } + if(sdt->version == 0) { + fprintf(stderr,"Null shared data version (maybe server turned off)\n"); + /*exit(1);*/ + } + else if(sdt->version != BTA_Data_Ver) { + fprintf(stderr,"Wrong shared data version: I'am - %d, but server - %d ...\n", + BTA_Data_Ver, sdt->version ); + /*exit(1);*/ + } + if(sdt->size != sdat.size) { + if(sdt->size > sdat.size) { + /* но клиент имеет право использовать начальную часть данных */ + fprintf(stderr,"Wrong shared area size: I needs - %d, but server - %d ...\n", + sdat.size, sdt->size ); + } else { + /* "залезание" в пустую резервную часть теперь тоже */ + /* будем оставлять на совести автора клиента! */ + fprintf(stderr,"Attention! Too little shared data structure!\n"); + sleep(1); + fprintf(stderr,"I needs - %d, but server gives only %d ...\n", + sdat.size, sdt->size ); + sleep(1); + fprintf(stderr,"May be server's version too old!?\n"); + /* exit(1); */ + + } + } + return; + } + /* ServerSide */ + if(sdt->magic != sdat.key.code || + sdt->version != BTA_Data_Ver || + sdt->size != sdat.size) { + + for(i=0; imagic = sdat.key.code; + sdt->version = BTA_Data_Ver; + sdt->size = sdat.size; + ServPID = 0; + UseModel = NoModel; + ClockType = Ch7_15; + Sys_Mode = SysStop; + Sys_Target = TagPosition; + Tel_Focus = Prime; + Tel_Hardware = Hard_On; + Tel_Mode = Automatic; + Az_Mode = Rev_Off; + P2_State = P2_Mode = P2_Off; + Foc_State = Foc_Off; + Dome_State = D_Off; + Pos_Corr = PC_On; + TrkOk_Mode = UseDiffVel | UseDiffAZ ; + InpAlpha=InpDelta= 0.; + SrcAlpha=SrcDelta= 0.; + VelAlpha=VelDelta= 0.; + CurAlpha=CurDelta= 0.; + InpAzim=InpZdist = 0.; + Diff_A=Diff_Z=Diff_P=0.0; + pos_cor_A=pos_cor_Z=refract_Z = 0.; + tel_cor_A=tel_cor_Z=tel_ref_Z = 0.; + vel_objA=vel_objZ=vel_objP = 0.; + diff_vA=diff_vZ=diff_vP=0.; + speedA = speedZ = speedP = 0.; + req_speedA = req_speedZ = req_speedP = 0.; + mod_vel_A=mod_vel_Z=mod_vel_P=mod_vel_F=mod_vel_D=0.; + code_KOST = 0; + M_time = S_time = L_time = 0.; + ppndd_A=ppndd_Z=ppndd_P=ppndd_B=0; + dup_A=dup_Z=dup_P=dup_F=dup_D=0; + low_A=low_Z=low_P=low_F=low_D=0; + code_A=code_Z=code_P=code_B=code_F=code_D=code_T1=code_T2=code_T3=code_Wnd=0; + val_A=val_Z=val_B=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + val_P=200*3600.; + val_F=100.; + vel_A=vel_Z=vel_P=vel_F=vel_D=0.; + for(i=0; imagic == sdat.key.code) && (sdt->version == BTA_Data_Ver) ); +} +static void bta_data_close() { + if(sdat.side == ServerSide) { + sdt->magic = 0; + sdt->version = 0; + } +} + +/* блок информационных сообщений ??? */ +/*struct SHM_Block info = {{'I','n','f','o',0},1024,1024,0444,SHM_RDONLY,NULL,NULL,NULL,0,-1,NULL};*/ + +/* Allocate shared memory segment */ +static void get_shm_block( struct SHM_Block *sb, int server) { + int getsize = (server)? sb->maxsize : sb->size; + + /* first try to find existing one */ + sb->id = shmget(sb->key.code, getsize, sb->mode); + + if (sb->id<0 && errno==ENOENT && server) { + /* if no - try to create a new one */ + int cresize = sb->maxsize; + if(sb->size > cresize) { + fprintf(stderr,"Wrong shm maxsize(%d) < realsize(%d)\n",sb->maxsize,sb->size); + cresize = sb->size; + } + sb->id = shmget(sb->key.code, cresize, IPC_CREAT|IPC_EXCL|sb->mode); + } + if (sb->id<0) { + char msg[80]; + if(server) + sprintf(msg,"Can't create shared memory segment '%s'",sb->key.name); + else + sprintf(msg,"Can't find shared segment '%s' (maybe no server process) ",sb->key.name); + perror(msg); + exit(errno); + } + /* attach it to our memory space */ + sb->addr = (unsigned char *)shmat ( sb->id, NULL, sb->atflag ); + + if ((long int)(sb->addr) == -1) { + char msg[80]; + sprintf(msg,"Can't attach shared memory segment '%s'",sb->key.name); + perror(msg); + exit(errno); + } + if(server) { + if((shmctl(sb->id, SHM_LOCK, NULL) < 0) < 0) { + char msg[80]; + sprintf(msg,"Can't prevents swapping of shared memory segment '%s'",sb->key.name); + perror(msg); + exit(errno); + } + } + fprintf(stderr,"Create&attach shared memory segment '%s' %dbytes at %x \n", + sb->key.name, sb->size, (unsigned long int)sb->addr); + + sb->side = server; + + if(sb->init!=NULL) + sb->init(); +} +static int close_shm_block( struct SHM_Block *sb) { + int ret; + if(sb->close != NULL) + sb->close(); + if(sb->side == ServerSide) { + ret = shmctl(sb->id, SHM_UNLOCK, NULL); +/* ret = shmctl(sb->id, IPC_RMID, NULL); */ + } + ret = shmdt (sb->addr); + return(ret); +} +#endif + +static int check_shm_block( struct SHM_Block *sb) { + if(sb->check != NULL) + return(sb->check()); + else return(1); +} + +#ifndef BTA_MODULE +int snd_id=-1; /* текущий (и единственный?) канал отсылки команд клиента */ +int cmd_src_pid=0; /* номер процесса источника для ОДНОЙ след.команды */ +unsigned int cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern unsigned int cmd_src_ip; +#endif + +#ifndef BTA_MODULE +/* Create|Find command queue */ +static void get_cmd_queue( struct CMD_Queue *cq, int server) { + if (!server && cq->id>=0) { /* if already in use */ + snd_id = cq->id; /* set current... */ + return; + } + /* first try to find existing one */ + cq->id = msgget(cq->key.code, cq->mode); + if (cq->id<0 && errno==ENOENT && server) + /* if no - try to create a new one */ + cq->id = msgget(cq->key.code, IPC_CREAT|IPC_EXCL|cq->mode); + if (cq->id<0) { + char msg[80]; + if(server) + sprintf(msg,"Can't create comand queue '%s'",cq->key.name); + else + sprintf(msg,"Can't find comand queue '%s' (maybe no server process) ",cq->key.name); + perror(msg); + exit(errno); + } + cq->side = server; + if (server) { + char buf[120]; /* выбросить все команды из очереди */ + while(msgrcv(cq->id, (struct msgbuf *)buf, 112, 0, IPC_NOWAIT)>0); + } else + snd_id = cq->id; + cq->acckey = 0; +} +#endif + +/* установка ключа доступа в тек. канале */ +static void set_acckey(unsigned int newkey) { + if (snd_id<0) return; + if(ucmd.id==snd_id) ucmd.acckey=newkey; + else if(ocmd.id==snd_id) ocmd.acckey=newkey; + else if(mcmd.id==snd_id) mcmd.acckey=newkey; +} + +/* установка данных источника для ОДНОЙ след.команды */ +/* если не подходят умолчания: IP=0(локальная команда) и PID текущ.процесса */ +static void set_cmd_src(unsigned int ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + int mtype; /* type of message */ + unsigned int acckey; /* ключ доступа клиента */ + unsigned int src_pid; /* номер процесса источника */ + unsigned int src_ip; /* IP-адр. источника, =0 - локальная команда */ + char mtext[100]; /* message text */ +}; +/* отсылка команд клиента к серверу */ +static void send_cmd(int cmd_code, char *buf, int size) { + struct my_msgbuf mbuf; + + if (snd_id<0) return; + if (size>100) size=100; + if (cmd_code>0) + mbuf.mtype = cmd_code; + else + return; + if(ucmd.id==snd_id) mbuf.acckey=ucmd.acckey; + else if(ocmd.id==snd_id) mbuf.acckey=ocmd.acckey; + else if(mcmd.id==snd_id) mbuf.acckey=mcmd.acckey; + + mbuf.src_pid = cmd_src_pid? cmd_src_pid : getpid(); + mbuf.src_ip = cmd_src_ip; + cmd_src_pid = cmd_src_ip = 0; + + if(size>0) + memcpy( mbuf.mtext, buf, size); + else { + mbuf.mtext[0] = 0; + size = 1; + } + msgsnd( snd_id, (struct msgbuf *)&mbuf, size+12, IPC_NOWAIT); +} +static void send_cmd_noarg(int cmd_code) { + send_cmd(cmd_code, NULL, 0); +} +static void send_cmd_str(int cmd_code, char *arg) { + send_cmd(cmd_code, arg, strlen(arg)+1); +} +static void send_cmd_i1(int cmd_code, int arg1) { + send_cmd(cmd_code, (char *)&arg1, sizeof(int)); +} +static void send_cmd_i2(int cmd_code, int arg1, int arg2) { + int ibuf[2]; + ibuf[0] = arg1; + ibuf[1] = arg2; + send_cmd(cmd_code, (char *)ibuf, 2*sizeof(int)); +} +static void send_cmd_i3(int cmd_code, int arg1, int arg2, int arg3) { + int ibuf[3]; + ibuf[0] = arg1; + ibuf[1] = arg2; + ibuf[2] = arg3; + send_cmd(cmd_code, (char *)ibuf, 3*sizeof(int)); +} +static void send_cmd_i4(int cmd_code, int arg1, int arg2, int arg3, int arg4) { + int ibuf[4]; + ibuf[0] = arg1; + ibuf[1] = arg2; + ibuf[2] = arg3; + ibuf[3] = arg4; + send_cmd(cmd_code, (char *)ibuf, 4*sizeof(int)); +} +static void send_cmd_d1(int cmd_code, double arg1) { + send_cmd(cmd_code, (char *)&arg1, sizeof(double)); +} +static void send_cmd_d2(int cmd_code, double arg1, double arg2) { + double dbuf[2]; + dbuf[0] = arg1; + dbuf[1] = arg2; + send_cmd(cmd_code, (char *)dbuf, 2*sizeof(double)); +} +static void send_cmd_i1d1(int cmd_code, int arg1, double arg2) { +#pragma pack(push,4) + struct { + int ival; + double dval; + } buf; +#pragma pack(pop) + buf.ival = arg1; + buf.dval = arg2; + send_cmd(cmd_code, (char *)&buf, sizeof(buf)); +} +static void send_cmd_i2d1(int cmd_code, int arg1, int arg2, double arg3) { + struct { + int ival[2]; + double dval; + } buf; + buf.ival[0] = arg1; + buf.ival[1] = arg2; + buf.dval = arg3; + send_cmd(cmd_code, (char *)&buf, sizeof(buf)); +} +static void send_cmd_i3d1(int cmd_code, int arg1, int arg2, int arg3, double arg4) { +#pragma pack(push,4) + struct { + int ival[3]; + double dval; + } buf; +#pragma pack(pop) + buf.ival[0] = arg1; + buf.ival[1] = arg2; + buf.ival[2] = arg3; + buf.dval = arg4; + send_cmd(cmd_code, (char *)&buf, sizeof(buf)); +} + +static void encode_lev_passwd(char *passwd, int nlev, unsigned int *keylev, unsigned int *codlev) { + char salt[4]; + char *encr; + union { + unsigned int ui; + char c[4]; + } key,cod; + sprintf(salt,"L%1d",nlev); + encr = (char *)crypt(passwd, salt); + cod.c[0] = encr[2]; + key.c[0] = encr[3]; + cod.c[1] = encr[4]; + key.c[1] = encr[5]; + cod.c[2] = encr[6]; + key.c[2] = encr[7]; + cod.c[3] = encr[8]; + key.c[3] = encr[9]; + *keylev = key.ui; + *codlev = cod.ui; +} + +static int find_lev_passwd(char *passwd, unsigned int *keylev, unsigned int *codlev) { + int nlev; + for(nlev=5; nlev>0; nlev--) { + encode_lev_passwd(passwd, nlev, keylev, codlev); + if(nlev == 1 && code_Lev1 == *codlev) break; + if(nlev == 2 && code_Lev2 == *codlev) break; + if(nlev == 3 && code_Lev3 == *codlev) break; + if(nlev == 4 && code_Lev4 == *codlev) break; + if(nlev == 5 && code_Lev5 == *codlev) break; + } + return(nlev); +} + +static int check_lev_passwd(char *passwd) { + unsigned int keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +}