diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..47eaad6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.hg +.hgignore +.dropbox.attr diff --git a/C/bta_pos/bta_pos.c b/C/bta_pos/bta_pos.c new file mode 100644 index 0000000..5bdb750 --- /dev/null +++ b/C/bta_pos/bta_pos.c @@ -0,0 +1,14 @@ +#include "bta_shdata.h" + +inline double sec2deg(double angle){ + return angle / 3600; +} + +int main(int argc, char** argv){ + get_shm_block( &sdat, ClientSide); + if(!check_shm_block(&sdat)) return -1; + printf("Access-Control-Allow-Origin: http://ishtar.sao.ru\n" + "Acess-Control-Allow-Methods: POST\nContent-type:multipart/form-data\n\n"); + printf("telA=%.2f telZ=%.2f domeA=%.2f\n", sec2deg(val_A), sec2deg(val_Z), sec2deg(val_D)); +} + diff --git a/C/bta_pos/bta_shdata.h b/C/bta_pos/bta_shdata.h new file mode 100644 index 0000000..49607dc --- /dev/null +++ b/C/bta_pos/bta_shdata.h @@ -0,0 +1,1158 @@ +#pragma once +#ifndef __BTA_SHDATA_H__ +#define __BTA_SHDATA_H__ + +#define _XOPEN_SOURCE 501 +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-braces" +#pragma GCC diagnostic ignored "-Wsequence-point" +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" + +//#define int __int32_t +#define uint __uint32_t + +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; /* дескриптор подсоединения */ + uint 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 + +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(4) +//struct __attribute__((packed)) BTA_Data { +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 - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + uint 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) /* время работы программы */ + uint 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) /* код датчика ППНДД давления */ + uint 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) /* код Грея датчика ДУП положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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 __attribute__((packed)) SysMesg { + 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]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + uint 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) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + uint 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_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 - " - */ + + uint code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +//struct __attribute__((packed)) SEWdata { +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + __uint32_t 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-контроллеров */ + uint 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 */ + uint 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 /* датчик дыма СПФ */ + uint 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 (мкм) */ + + /* флаги блокировки управления узлами */ + __uint32_t 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-контроллера купола */ + uint 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 + +}; + +#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_P=val_B=val_F=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + 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 ((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, (uint)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; /* номер процесса источника для ОДНОЙ след.команды */ +__uint32_t cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern __uint32_t 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(uint 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(__uint32_t ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + __int32_t mtype; /* type of message */ + __uint32_t acckey; /* ключ доступа клиента */ + __uint32_t src_pid; /* номер процесса источника */ + __uint32_t 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) { + struct { + int ival; + double dval; + } buf; + 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) { + struct { + int ival[3]; + double dval; + } buf; + 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, uint *keylev, uint *codlev) { + char salt[4]; + char *encr; + union { + uint 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, uint *keylev, uint *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) { + uint keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +} + +#pragma GCC diagnostic pop + +#endif // __BTA_SHDATA_H__ diff --git a/C/bta_shdata.h b/C/bta_shdata.h new file mode 100644 index 0000000..49607dc --- /dev/null +++ b/C/bta_shdata.h @@ -0,0 +1,1158 @@ +#pragma once +#ifndef __BTA_SHDATA_H__ +#define __BTA_SHDATA_H__ + +#define _XOPEN_SOURCE 501 +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-braces" +#pragma GCC diagnostic ignored "-Wsequence-point" +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" + +//#define int __int32_t +#define uint __uint32_t + +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; /* дескриптор подсоединения */ + uint 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 + +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(4) +//struct __attribute__((packed)) BTA_Data { +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 - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + uint 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) /* время работы программы */ + uint 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) /* код датчика ППНДД давления */ + uint 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) /* код Грея датчика ДУП положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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 __attribute__((packed)) SysMesg { + 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]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + uint 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) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + uint 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_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 - " - */ + + uint code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +//struct __attribute__((packed)) SEWdata { +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + __uint32_t 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-контроллеров */ + uint 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 */ + uint 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 /* датчик дыма СПФ */ + uint 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 (мкм) */ + + /* флаги блокировки управления узлами */ + __uint32_t 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-контроллера купола */ + uint 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 + +}; + +#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_P=val_B=val_F=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + 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 ((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, (uint)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; /* номер процесса источника для ОДНОЙ след.команды */ +__uint32_t cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern __uint32_t 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(uint 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(__uint32_t ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + __int32_t mtype; /* type of message */ + __uint32_t acckey; /* ключ доступа клиента */ + __uint32_t src_pid; /* номер процесса источника */ + __uint32_t 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) { + struct { + int ival; + double dval; + } buf; + 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) { + struct { + int ival[3]; + double dval; + } buf; + 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, uint *keylev, uint *codlev) { + char salt[4]; + char *encr; + union { + uint 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, uint *keylev, uint *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) { + uint keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +} + +#pragma GCC diagnostic pop + +#endif // __BTA_SHDATA_H__ diff --git a/C/bta_shdata.h.old b/C/bta_shdata.h.old new file mode 100644 index 0000000..70189e3 --- /dev/null +++ b/C/bta_shdata.h.old @@ -0,0 +1,1141 @@ + +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ +#include +#include +#include +#include +#include +#include + + +//#define int __int32_t +//#define uint __uint32_t + +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; /* дескриптор подсоединения */ + uint 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 + +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(4) +//struct __attribute__((packed)) BTA_Data { +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 - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + uint 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) /* время работы программы */ + uint 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) /* код датчика ППНДД давления */ + uint 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) /* код Грея датчика ДУП положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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 __attribute__((packed)) SysMesg { + 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]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + uint 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) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + uint 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_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 - " - */ + + uint code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +//struct __attribute__((packed)) SEWdata { +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + __uint32_t 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-контроллеров */ + uint 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 */ + uint 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 /* датчик дыма СПФ */ + uint 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 (мкм) */ + + /* флаги блокировки управления узлами */ + __uint32_t 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-контроллера купола */ + uint 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 + +}; + +#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_P=val_B=val_F=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + 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 ((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, (uint)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; /* номер процесса источника для ОДНОЙ след.команды */ +__uint32_t cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern __uint32_t 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(uint 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(__uint32_t ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + __int32_t mtype; /* type of message */ + __uint32_t acckey; /* ключ доступа клиента */ + __uint32_t src_pid; /* номер процесса источника */ + __uint32_t 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) { + struct { + int ival; + double dval; + } buf; + 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) { + struct { + int ival[3]; + double dval; + } buf; + 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, uint *keylev, uint *codlev) { + char salt[4]; + char *encr; + union { + uint 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, uint *keylev, uint *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) { + uint keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +} diff --git a/C/client_cli/Makefile b/C/client_cli/Makefile new file mode 100644 index 0000000..ad29ef3 --- /dev/null +++ b/C/client_cli/Makefile @@ -0,0 +1,12 @@ +CXX.SRCS = tempmon_cli +CC = gcc +LDFLAGS = +CPPFLAGS = +all : tempmon_cli clean +tempmon_cli : client_cli.o + $(CC) client_cli.c $(CPPFLAGS) -o tempmon_cli +clean: + /bin/rm -f *.o *~ + +### +# name1.o : header1.h header2.h ... diff --git a/C/client_cli/bta_shdata.h b/C/client_cli/bta_shdata.h new file mode 100644 index 0000000..49607dc --- /dev/null +++ b/C/client_cli/bta_shdata.h @@ -0,0 +1,1158 @@ +#pragma once +#ifndef __BTA_SHDATA_H__ +#define __BTA_SHDATA_H__ + +#define _XOPEN_SOURCE 501 +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-braces" +#pragma GCC diagnostic ignored "-Wsequence-point" +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" + +//#define int __int32_t +#define uint __uint32_t + +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; /* дескриптор подсоединения */ + uint 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 + +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(4) +//struct __attribute__((packed)) BTA_Data { +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 - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + uint 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) /* время работы программы */ + uint 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) /* код датчика ППНДД давления */ + uint 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) /* код Грея датчика ДУП положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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 __attribute__((packed)) SysMesg { + 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]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + uint 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) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + uint 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_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 - " - */ + + uint code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +//struct __attribute__((packed)) SEWdata { +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + __uint32_t 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-контроллеров */ + uint 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 */ + uint 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 /* датчик дыма СПФ */ + uint 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 (мкм) */ + + /* флаги блокировки управления узлами */ + __uint32_t 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-контроллера купола */ + uint 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 + +}; + +#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_P=val_B=val_F=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + 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 ((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, (uint)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; /* номер процесса источника для ОДНОЙ след.команды */ +__uint32_t cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern __uint32_t 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(uint 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(__uint32_t ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + __int32_t mtype; /* type of message */ + __uint32_t acckey; /* ключ доступа клиента */ + __uint32_t src_pid; /* номер процесса источника */ + __uint32_t 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) { + struct { + int ival; + double dval; + } buf; + 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) { + struct { + int ival[3]; + double dval; + } buf; + 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, uint *keylev, uint *codlev) { + char salt[4]; + char *encr; + union { + uint 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, uint *keylev, uint *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) { + uint keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +} + +#pragma GCC diagnostic pop + +#endif // __BTA_SHDATA_H__ diff --git a/C/client_cli/client_cli.c b/C/client_cli/client_cli.c new file mode 100644 index 0000000..0073fb9 --- /dev/null +++ b/C/client_cli/client_cli.c @@ -0,0 +1,360 @@ +// client.c +// +// Copyright 2012 Edward V. Emelianoff +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. + + +#define __CLIENT_C__ +#include +#include +#include +#include +#include "defines.h" +#include "lang.h" + +#define Julian(x) ((double)x/86400. + 2440587.5) + +extern const char *__progname; + +char *db_path = A_PATH; +off_t starting_pos = 0LL; +typedef struct shm_data shm_d; +unsigned char Lang = 1; // английский +time_t t_start = 0, t_end = 0; +time_t aver_interval = 1; +int force_dbpath = 0; +int out_fd; +int only_extr = 0; + +inline void minmax(float *min, float *max, float param){ + if(param > *max) *max = param; + else if(param < *min) *min = param; +} + +void send_data(unsigned char stat_mask){ + int ii=0, j; + uint64_t data_amount = 0; + struct tm ltime; + time_t t_first=0, t_last=0; + double otemp=0., itemp=0., mtemp=0., wind=0., pres=0., hum=0.; + double otmax=-1e6,otmin=1e6,itmax=-1e6,itmin=1e6,mtmax=-1e6,mtmin=1e6,windmax=-1e6,windmin=1e6; + int ctr, status, statuses[5] = {0,0,0,0,0}; + char s_time[32]; + monit_d data; + if(!only_extr){ + printf("OT - %s\nIT - %s\nMT - %s\nWS - %s\nP - %s\nH - %s\nS - %s\n\n", + _L(_s_Otemp_), _L(_s_Itemp_), _L(_s_Mtemp_), + _L(_s_WSpeed_), _L(_s_Pressure_), _L(_s_Humidity_), + _L(_s_State_)); + printf("%s\t\tJulian date\tOT\tIT\tMT\tWS\tP\tH\tS\n", _L(_s_Date_)); + } + while(read(out_fd, &data, sizeof(data)) > 0){ + time_t X = (time_t) data.seconds; + //printf("time: %zd (tstart: %zd, tend: %zd) -- %s", data.seconds, t_start, t_end, ctime(&X)); + if(X < t_start) continue; + if(X > t_end) break; + if(!(stat_mask & (1 << data.status))) continue; + data_amount++; + if(!only_extr){ + if(t_first == 0) t_first = t_last = X; + else if((X - t_first) >= aver_interval){ // накопили достаточно данных + t_first = t_first/2 + t_last/2; // середина временного интервала + ltime = *localtime(&t_first);//*localtime(&t_first); + strftime(s_time, 32, "%d/%m/%Y, %H:%M:%S", <ime); + if(ii == 0) ii = 1; + ctr = 0; + for(j = 0; j<5; j++){ + if(statuses[j] > ctr){ + ctr = statuses[j]; + status = j; + } + statuses[j] = 0; + } + printf("%s\t%.6f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d\n", + s_time, + Julian(t_first), + otemp/ii, + itemp/ii, + mtemp/ii, + wind/ii, + pres/ii, + hum/ii, + status); + t_first = X; + otemp=itemp=mtemp=wind=pres=hum=0.; + ii = 0; + } + t_last = X; + otemp += data.outdoor_temp; + itemp += data.indoor_temp; + mtemp += data.mirror_temp; + wind += data.wind_speed; + pres += data.pressure; + hum += data.humidity; + statuses[data.status]++; + ii++; + } + if(otmax < data.outdoor_temp) otmax = data.outdoor_temp; + if(otmin > data.outdoor_temp) otmin = data.outdoor_temp; + if(itmax < data.indoor_temp) itmax = data.indoor_temp; + if(itmin > data.indoor_temp) itmin = data.indoor_temp; + if(mtmax < data.mirror_temp) mtmax = data.mirror_temp; + if(mtmin > data.mirror_temp) mtmin = data.mirror_temp; + if(windmax < data.wind_speed) windmax = data.wind_speed; + if(windmin > data.wind_speed) windmin = data.wind_speed; + } + if(!data_amount){ + printf("No data found!\n"); + return; + } + printf("\n\nExtremal values (min / max):\n"); + printf("%s: %g / %g\n", _L(_s_Otemp_), otmin, otmax); + printf("%s: %g / %g\n", _L(_s_Itemp_), itmin, itmax); + printf("%s: %g / %g\n", _L(_s_Mtemp_), mtmin, mtmax); + printf("%s: %g / %g\n", _L(_s_WSpeed_),windmin, windmax); +} + +void find_starting_pos(){ // ищем в кэше смещение для начала поиска + int cache_fd; + Cache cache; + if(force_dbpath){ + char cname[256]; + snprintf(cname, 255, "%s/.cache", db_path); + printf("using cache file %s\n", cname); + cache_fd = open(cname, O_RDONLY); + }else{ + if((cache_fd = open(CACHE_FILE, O_RDONLY)) < 0) + cache_fd = open("./cache", O_RDONLY); + } + if(cache_fd < 0){ + WARN(_L(_s_Cant_open_cache_)); + exit(1); + } + while(read(cache_fd, &cache, sizeof(cache)) > 0){ + //time_t X = (time_t) cache.time; + //printf("time: %zd -- %s", cache.time, ctime(&X)); + if(cache.time < t_start) + starting_pos = cache.offset; + else break; + } + //printf("pos: %zd \n", starting_pos); + close(cache_fd); +} + +time_t get_date(char *line){ + time_t date = time(NULL); + struct tm time_, time_now; + time_now = *localtime(&date); + time_.tm_sec = 0; + if(sscanf(line, "%d/%d/%d-%d:%d", &time_.tm_mday, &time_.tm_mon, &time_.tm_year, + &time_.tm_hour, &time_.tm_min) == 5){time_.tm_mon -= 1;} + else if(!strchr(line, ':') && sscanf(line, "%d/%d/%d", &time_.tm_mday, &time_.tm_mon, &time_.tm_year) == 3){ + date = -1; time_.tm_mon -= 1;} + else if(!strchr(line, ':') && sscanf(line, "%d/%d", &time_.tm_mday, &time_.tm_mon) == 2){ + date = -1; time_.tm_mon -= 1; time_.tm_year = time_now.tm_year;} + else if(sscanf(line, "%d:%d", &time_.tm_hour, &time_.tm_min) == 2){ + time_.tm_year = time_now.tm_year; time_.tm_mon = time_now.tm_mon; + time_.tm_mday = time_now.tm_mday;} + else if(!strchr(line, ':') && !strchr(line, '/') && !strchr(line, '.') && !strchr(line, '-') + && sscanf(line, "%d", &time_.tm_mon) == 1){ + date = -1; time_.tm_mon -= 1; time_.tm_year = time_now.tm_year; + time_.tm_mday = 1;} + else{ + printf("\nWrong datetime format!\n"); + printf("Formats: D/M/Y-hh:mm, D/M/Y, hh:mm, D/M, M\n"); + exit(1); + } + if(date == -1){ + time_.tm_hour = 0; + time_.tm_min = 0; + } + if(time_.tm_mon > 11 || time_.tm_mon < 0){ + printf("\nMonth should be in 1..12\n"); + exit(2); + } + if(time_.tm_mday > 31 || time_.tm_mday < 1){ + printf("\nDate should be in 1..31, %d\n", time_.tm_mday); + exit(3); + } + if(time_.tm_year > 1900) time_.tm_year -= 1900; + else if(time_.tm_year > -1 && time_.tm_year < 100) time_.tm_year += 100; + else if(time_.tm_year < 0 || time_.tm_year > 200){ + printf("\nBad year format %d\n", time_.tm_year); + exit(4); + } + if(time_.tm_hour > 23 || time_.tm_hour < 0){ + printf("\nTime should be in 0..23\n"); + exit(5); + } + if(time_.tm_min > 59 || time_.tm_min < 0){ + printf("\nMinutes should be in 0..59\n"); + exit(6); + } + date = mktime(&time_); + return date; +} + +void print_dates(){ + char s_time[32]; + inline char *mktm(uint32_t t){ + time_t X = (time_t) t; + struct tm ltime = *localtime(&X); + strftime(s_time, 32, "%d/%m/%Y, %H:%M:%S", <ime); + return s_time; + } + monit_d data; + if(read(out_fd, &data, sizeof(data)) != sizeof(data)){ + WARN("Error reading datafile!\n"); + exit(1); + } + printf("Date of first record in database: %s\n", mktm(data.seconds)); + lseek(out_fd, -sizeof(data), SEEK_END); + if(read(out_fd, &data, sizeof(data)) != sizeof(data)){ + WARN("Error reading datafile!\n"); + exit(1); + } + printf("Date of last record in database: %s\n", mktm(data.seconds)); + exit(0); +} + +unsigned char get_modemask(const char *optarg){ + unsigned char mode = 0; + char c; + while((c = *optarg++)){ + switch (c){ + case 's': case 'S': + mode |= 1; + break; + case 'g': case 'G': + mode |= 2; + break; + case 'r': case 'R': + mode |= 4; + break; + case 'u': case 'U': + mode |= 8; + break; + case 'o': case 'O': + mode |= 16; + break; + default: + WARN("Bad mode: should be sgruo\n"); + exit(1); + } + } + return mode; +} + +void usage(char *fmt, ...){ + va_list ap; + va_start(ap, fmt); + printf("\n"); + if (fmt != NULL){ + vprintf(fmt, ap); + printf("\n\n"); + } + va_end(ap); + printf("Usage:\t%s [options]\n", + __progname); + printf("\tOptions:\n"); + printf("\t-d, --dbpath\t\tPath to database files\n"); + printf("\t-e, --tend\t\tEnding time (D/M/Y-hh:mm)\n"); + printf("\t-h, --help\t\tShow this help\n"); + printf("\t-i, --averint\t\tTime interval for data averaging (in seconds)\n"); + printf("\t-l, --lookout\t\t Show date interval of stored data\n"); + printf("\t-m, --mode\t\tTelescope mode (sgruo - Stopped, Guiding, Ready, Unknown, Opened)\n"); + printf("\t-s, --tstart\t\tStarting time (D/M/Y-hh:mm)\n"); + printf("\t-X, --extremal\t\tOnly show extremal values\n"); + exit(0); +} + +int main(int argc, char **argv){ + unsigned char mask = 0; + struct option long_options[] = { + {"dbpath", 1, 0, 'd'}, + {"tend", 1, 0, 'e'}, + {"help", 0, 0, 'h'}, + {"averint", 1, 0, 'i'}, + {"lookout", 0, 0, 'l'}, + {"mode", 1, 0, 'm'}, + {"tstart", 1, 0, 's'}, + {"extremal", 0, 0, 'X'} + }; + char short_options[] = "d:e:hi:lm:s:X"; + int lookout = 0; + while (1){ + int opt; + if((opt = getopt_long(argc, argv, short_options, + long_options, NULL)) == -1) break; + switch(opt){ + case 'd': + db_path = strdup(optarg); + force_dbpath = 1; + break; + case 'e': + t_end = get_date((char*)optarg); + break; + case 'h': + usage(NULL); + break; + case 'i': + aver_interval = atoi((char*)optarg); + if(aver_interval < 1) aver_interval = 1; + break; + case 'l': + lookout = 1; + break; + case 'm': + mask = get_modemask(optarg); + break; + case 's': + t_start = get_date((char*)optarg); + break; + case 'X': + only_extr = 1; + break; + default: + usage("Unknown argument"); + } + } + if(argc != optind) usage("Too many arguments"); + if(t_end < 1) t_end = time(NULL); + if(t_end <= t_start){ + WARN("%s\n", _L(_s_Bad_date_)); + return(1); + } + if(mask == 0) mask = 0xff; + if(force_dbpath){ + char cname[256]; + snprintf(cname, 255, "%s/.out", db_path); + printf("using DB file %s\n", cname); + out_fd = open(cname, O_RDONLY); + }else{ + if((out_fd = open(OUT_FILE, O_RDONLY)) < 0) + out_fd = open("./out", O_RDONLY); + } + if(out_fd < 0){ + WARN(_L(_s_Cant_open_data_)); + return(1); + } + if(lookout) print_dates(); + find_starting_pos(); + lseek(out_fd, starting_pos, SEEK_SET); + send_data(mask); + return(0); +} + diff --git a/C/client_cli/defines.h b/C/client_cli/defines.h new file mode 100644 index 0000000..068acf5 --- /dev/null +++ b/C/client_cli/defines.h @@ -0,0 +1,78 @@ +#ifndef __DEFINES_H__ +#define __DEFINES_H__ +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __CLIENT_C__ +#include "bta_shdata.h" +#endif + +#define WARN(...) do{fprintf(stderr, __VA_ARGS__);}while(0) + +#define TIMEINTERVAL 9.99 // интервал усреднения данных (в секундах) +#define LOG_FILE "/Users/eddy/_data/.temp_daemon" // файл с логами +#define CACHE_FILE "/Users/eddy/_data/.cache" // индексный файл +#define OUT_FILE "/Users/eddy/_data/.out" // сама информация +#define PID_FILE "/Users/eddy/_data/.pid" // PID +#define A_PATH "/Users/eddy/_data" +#define PROC_BASE "/proc" +#define SHM_KEY 1234567890 +#define CACHE_EVERY_PWR 10 // кэшируем каждую 2^CACHE_EVERY_PWR запись +#define tell(fd) lseek(fd, 0, SEEK_CUR) + +enum telescope_status{ + STOP, // 0 - телескоп выключен + GUIDING, // 1 - ведение + READY, // 2 - все остановлено, питание есть + OTHER, // 3 - наведение или прочее перемещение телескопа/купола + OPEN // 4 - забрало открыто, идут наблюдения + // 5 - ЗАРЕЗЕРВИРОВАНО для суммарного времени +}; +typedef enum telescope_status Status; +typedef float data_type; +#pragma pack(4) +struct monitoring_data{ + uint32_t seconds; // время в секундах + data_type outdoor_temp; // медиана температуры за TIMEINTERVAL снаружи + data_type indoor_temp; // -//- температура внутри + data_type mirror_temp; // -//- температура зеркала + data_type wind_speed; // максимальная за TIMEINTERVAL скорость ветра + data_type pressure; // медианное значение давления (мм.рт.ст) + data_type humidity; // -//- влажности +/* data_type sigma_ot; // стандартное отклонение внешней температуры + data_type sigma_it; // -//- внутренней температуры + data_type sigma_mt; // -//- температуры зеркала + data_type sigma_w; // -//- скорости ветра + data_type sigma_p; + data_type sigma_h; + data_type avr_ot; // среднее за TIMEINTERVAL значение внешней температуры + data_type avr_it; // ... + data_type avr_mt; + data_type avr_w; + data_type avr_p; + data_type avr_h;*/ + Status status; // состояние телескопа +}; +typedef struct monitoring_data monit_d; + +#pragma pack(4) +struct _cache{ // структура для хранения данных в кэше + uint32_t time; // время в секундах с 1.01.1970-0:0 + uint64_t offset; // смещение в лог-файле +}; +typedef struct _cache Cache; +int *Visor = NULL; // состояние забрала +#endif + diff --git a/C/client_cli/lang.h b/C/client_cli/lang.h new file mode 100644 index 0000000..ff8877b --- /dev/null +++ b/C/client_cli/lang.h @@ -0,0 +1,55 @@ +#define _LANG(_var, _ru, _en) char _var##ru[] = _ru;\ + char _var##en[] = _en;\ + char *_var[2] = {_var##ru, _var##en}; +#define _L(x) (x[Lang]) + +_LANG(_s_Save_file_, "Сохранить файл", "Save file"); +_LANG(_s_no_QS_, "Отсутствует строка запроса", "No query string"); +_LANG(_s_no_tstart_, "Пожалуйста, заполните форму\"начальное время\"", "Please, fill the form \"starting time\""); +_LANG(_s_Date_, "Дата и время", "Date and time"); +_LANG(_s_Otemp_, "Внешняя температура", "Outdoor temperature"); +_LANG(_s_Itemp_, "Внутренняя температура", "Indoor temperature"); +_LANG(_s_Mtemp_, "Температура зеркала", "Mirror temperature"); +_LANG(_s_Ot_, "Внешняя", "Outdoor"); +_LANG(_s_It_, "Внутренняя", "Indoor"); +_LANG(_s_Mt_, "Зеркала", "Mirror"); +_LANG(_s_WSpeed_, "Скорость ветра", "Wind speed"); +_LANG(_s_Temp_, "Температура", "Temperature"); +_LANG(_s_Pressure_, "Давление (мм.рт.ст.)", "Pressure (mmHg)"); +_LANG(_s_Humidity_, "Влажность (%)", "Humidity (%)"); +_LANG(_s_State_, "Состояние телескопа", "Telescope state"); +_LANG(_s_Monlen_, "Сделано измерений", "Number of measurements"); +_LANG(_s_SVGerr_, "Не могу создать график", "Can't create graph"); +_LANG(_s_Bad_date_, "Неправильный формат даты, или дата окончания раньше даты начала", "Bad date format, or starting date goes after ending date"); +_LANG(_s_Cant_open_cache_, "Не могу открыть файл кэша", "Can't open cache file"); +_LANG(_s_Cant_open_data_, "Не могу открыть файл с данными", "Can't open data file"); +_LANG(_s_Cant_write_, "Ошибка записи данных", "Can't write data"); +_LANG(_s_noData_, "За указанный период нет данных", "No data for this period"); +_LANG(_s_Vopen_, "Забрало открыто", "Visor is open"); +_LANG(_s_Vclose_, "Забрало закрыто", "Visor is close"); +_LANG(_s_CurVstat_, "Текущее состояние", "Current status"); +_LANG(_s_ChVstat_, "Сменить состояние на", "Change status to"); +_LANG(_s_noVisor_, "Не могу определить состояние забрала", "Can't define visor state"); +_LANG(_s_No_Data_, "Недостаточно данных", "Not enough data"); +_LANG(_s_Gtr_, "больше", "greater"); +_LANG(_s_Less_, "меньше", "less"); +_LANG(_s_G_mustbe_less_L_, "Число в поле \"больше\" должно быть меньше числа в поле \"меньше\"", + "The value in field \"greater\" must be less than value in field \"less\""); +_LANG(_s_L_mustbe_less_G_, "Число в поле \"меньше\" должно быть меньше числа в поле \"больше\"", + "The value in field \"less\" must be less than value in field \"greater\""); +_LANG(_s_Max_data_, "Даты с максимальным значением параметров", "Dates with maximum of paremeters"); +_LANG(_s_Min_data_, "Даты с минимальным значением параметров", "Dates with minimum of paremeters"); +_LANG(_s_Diapazon_, "Данные из выбранного диапазона:", "Data from selected range:"); +_LANG(_s_Modes_, "Режимы работы", "Work modes"); +_LANG(_s_And_, "и", "and"); +_LANG(_s_Or_, "или", "or"); +_LANG(_s_Mode_Times_, "Суммарное время работы в режимах", "Total work time in modes"); +_LANG(_s_seconds_, "секунд", "seconds"); +_LANG(_s_days_, "суток", "days"); +_LANG(_s_Stopped_, "Полный останов", "Full stop"); +_LANG(_s_Guiding_, "Сопровождение объекта", "Object guiding"); +_LANG(_s_Ready_, "Готов", "Ready"); +_LANG(_s_Other_, "Прочее", "Other"); +_LANG(_s_Total_, "Итого", "Total"); +//_LANG(, "", ""); + diff --git a/C/daemon/Makefile b/C/daemon/Makefile new file mode 100644 index 0000000..7f88e5b --- /dev/null +++ b/C/daemon/Makefile @@ -0,0 +1,15 @@ +CC = gcc +LDFLAGS = -lcrypt +CPPFLAGS = +all : daemon tempmon tempmon_cli clean +daemon : daemon.o + $(CC) $(LDFLAGS) daemon.c $(CPPFLAGS) -o daemon +tempmon : client.o + $(CC) client.c $(CPPFLAGS) -o tempmon +tempmon_cli : client_cli.o + $(CC) client_cli.c $(CPPFLAGS) -o tempmon_cli +clean: + /bin/rm -f *.o *~ + +### +# name1.o : header1.h header2.h ... diff --git a/C/daemon/bta_shdata.h b/C/daemon/bta_shdata.h new file mode 100644 index 0000000..49607dc --- /dev/null +++ b/C/daemon/bta_shdata.h @@ -0,0 +1,1158 @@ +#pragma once +#ifndef __BTA_SHDATA_H__ +#define __BTA_SHDATA_H__ + +#define _XOPEN_SOURCE 501 +/* Основные определения и функции поддержки межпрограммного интерфейса */ +/* Возможные внешние определения: */ +/* BTA_MODULE - при исп-и в доп. C-модулях (не в главн.программе) */ +/* SHM_OLD_SIZE - для генерации предыдущей весии структуры БТА-данных */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-braces" +#pragma GCC diagnostic ignored "-Wsequence-point" +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#pragma GCC diagnostic ignored "-Wimplicit-function-declaration" + +//#define int __int32_t +#define uint __uint32_t + +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; /* дескриптор подсоединения */ + uint 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 + +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(4) +//struct __attribute__((packed)) BTA_Data { +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 - " - */ + + + /* результаты измерения датчиков и рассчитанные по ним значения */ + uint 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) /* время работы программы */ + uint 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) /* код датчика ППНДД давления */ + uint 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) /* код Грея датчика ДУП положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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) /* код отсчета положения купола */ + uint 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 __attribute__((packed)) SysMesg { + 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]) + + /* управление доступом */ + /* коды установки уровней доступа для клиентов */ + uint 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) /* "главный оператор" - все операции */ + /* ограничение сетевого доступа */ + uint 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_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 - " - */ + + uint code_sew; +#define code_SEW (sdt->code_sew) /* код спец.доступа к SEW-контроллерам */ + +/* параметры SEW-контроллеров */ +//struct __attribute__((packed)) SEWdata { +struct SEWdata { + int status; + double set_speed; + double mes_speed; + double current; + int index; + union { + unsigned char b[4]; + __uint32_t 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-контроллеров */ + uint 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 */ + uint 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 /* датчик дыма СПФ */ + uint 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 (мкм) */ + + /* флаги блокировки управления узлами */ + __uint32_t 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-контроллера купола */ + uint 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 + +}; + +#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_P=val_B=val_F=val_D=val_T1=val_T2=val_T3=val_Wnd=val_Alp=val_Del=0.; + 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 ((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, (uint)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; /* номер процесса источника для ОДНОЙ след.команды */ +__uint32_t cmd_src_ip=0; /* IP-адр. источника для ОДНОЙ след.команды */ +#else +extern int snd_id; +extern int cmd_src_pid; +extern __uint32_t 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(uint 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(__uint32_t ip, int pid) { + cmd_src_pid = pid; + cmd_src_ip = ip; +} + +/* структура сообщения */ +struct my_msgbuf { + __int32_t mtype; /* type of message */ + __uint32_t acckey; /* ключ доступа клиента */ + __uint32_t src_pid; /* номер процесса источника */ + __uint32_t 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) { + struct { + int ival; + double dval; + } buf; + 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) { + struct { + int ival[3]; + double dval; + } buf; + 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, uint *keylev, uint *codlev) { + char salt[4]; + char *encr; + union { + uint 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, uint *keylev, uint *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) { + uint keylev,codlev; + int nlev; + nlev = find_lev_passwd(passwd, &keylev, &codlev); + if(nlev>0) set_acckey(keylev); + return(nlev); +} + +#pragma GCC diagnostic pop + +#endif // __BTA_SHDATA_H__ diff --git a/C/daemon/client.c b/C/daemon/client.c new file mode 100644 index 0000000..cc83a0c --- /dev/null +++ b/C/daemon/client.c @@ -0,0 +1,682 @@ +// client.c +// +// Copyright 2012 Edward V. Emelianoff +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. + + +#define __CLIENT_C__ +#include +#include "defines.h" +#include "lang.h" +#include "quick_median.c" + +#define MAX_QUERY_SIZE 1024 // максимальный объем данных, передаваемых в запросе +#define SVG 0 // изображение - svg (этот параметр должен быть самым первым) +#define JPG 1 +//#define JPG 1 -> GIF = 2 +#define GIF 2 // изображение - gif (должен быть самым последним) + +static char* Content_type = "Content-type: multipart/form-data; charset=koi8-r\n\n"; +static char* SCRIPT_PATH = "/cgi-bin/eddy/tempmon"; // полный путь к скрипту +char *qs = NULL, *buf = NULL; +unsigned char Lang = 1; // английский +long long starting_pos = 0LL; +typedef struct shm_data shm_d; +int Graph = 0; +time_t t_start, t_end; +time_t aver_interval = 1; +int out_fd; +void sendSVG(const int image_type, unsigned char stat_mask, int im_height); + +inline void minmax(float *min, float *max, float param){ + if(param > *max) *max = param; + else if(param < *min) *min = param; +} + +void print_curvals(unsigned char stat_mask){ // stat_mask - битовая маска для Status + int i=1, f, d_len = 0; + monit_d data; + float max_otemp, min_otemp, avr_otemp, // внешняя температура + max_itemp, min_itemp, avr_itemp, // внутренняя температура + max_mtemp, min_mtemp, avr_mtemp, // температура зеркала + max_wind, min_wind, avr_wind, // скорость ветра + max_pres, min_pres, avr_pres, // давление + max_hmd, min_hmd, avr_hmd; // влажность + printf(Content_type); + while(read(out_fd, &data, sizeof(data)) == sizeof(data)){ + if(data.seconds < t_start) continue; + if(data.seconds > t_end) break; + if(!(stat_mask & (1 << data.status))) continue; + d_len++; + if(i){ + max_otemp = min_otemp = avr_otemp = data.outdoor_temp; + max_itemp = min_itemp = avr_itemp = data.indoor_temp; + max_mtemp = min_mtemp = avr_mtemp = data.mirror_temp; + max_wind = min_wind = avr_wind = data.wind_speed; + max_pres = min_pres = avr_pres = data.pressure; + max_hmd = min_hmd = avr_hmd = data.humidity; + i = 0; + }else{ + minmax(&min_otemp, &max_otemp, data.outdoor_temp); + minmax(&min_itemp, &max_itemp, data.indoor_temp); + minmax(&min_mtemp, &max_mtemp, data.mirror_temp); + minmax(&min_wind, &max_wind, data.wind_speed); + minmax(&min_pres, &max_pres, data.pressure); + minmax(&min_hmd, &max_hmd, data.humidity); + avr_otemp += data.outdoor_temp; + avr_itemp += data.indoor_temp; + avr_mtemp += data.mirror_temp; + avr_wind += data.wind_speed; + avr_pres += data.pressure; + avr_hmd += data.humidity; + } + } + if(d_len < 1){ + printf("%s", _L(_s_noData_)); + return; + } + printf("\n" +"" +"\n" +"\n" +"\n" +"\n" +"
%s%s%s%s
%s%s%s
min%.2f%.2f%.2f%.2f%.2f%.2f
max%.2f%.2f%.2f%.2f%.2f%.2f
avr%.2f%.2f%.2f%.2f%.2f%.2f
\n" + "%s: %d

\n", + _L(_s_Temp_), _L(_s_WSpeed_), _L(_s_Pressure_), _L(_s_Humidity_), + _L(_s_Ot_), _L(_s_It_), _L(_s_Mt_), + min_otemp, min_itemp, min_mtemp, min_wind, min_pres, min_hmd, + max_otemp, max_itemp, max_mtemp, max_wind, max_pres, max_hmd, + avr_otemp/d_len, avr_itemp/d_len, avr_mtemp/d_len, + avr_wind/d_len, avr_pres/d_len, avr_hmd/d_len, + _L(_s_Monlen_), d_len); + printf("%s\n", + SCRIPT_PATH, t_start, t_end, stat_mask, aver_interval, _L(_s_Save_file_)); +} + +char* get_qs(char* buf, int l){ + char *m, *qs = NULL; + if((m = getenv("REQUEST_METHOD")) && strcasecmp(m, "POST") == 0) + qs = fgets(buf, l, stdin); + else if( (qs = getenv("QUERY_STRING")) ) + qs = strncpy(buf, qs, l); + if(qs && strlen(qs) < 1) qs = NULL; + return qs; +} + +int get_qs_param(char *qs, char *param, char *meaning, int l){ + char *tok, *val, *par, *str; + int stat = 0; + str = calloc(MAX_QUERY_SIZE, 1); + strncpy(str, qs, MAX_QUERY_SIZE); + tok = strtok(str, "& \n"); + do{ + if((val = strchr(tok, '=')) == NULL) continue; + *val++ = '\0'; + par = tok; + if(strcasecmp(par, param)==0){ + if(strlen(val) > 0){ + stat = 1; + strncpy(meaning, val, l); + meaning[l-1] = 0; + } + break; + } + }while((tok = strtok(NULL, "& \n"))!=NULL); + free(str); + return stat; +} + +void send_data(unsigned char stat_mask){ + int ii=0, j; + struct timeval tv; + struct tm ltime; + time_t t_first=0, t_last=0; + double otemp=0., itemp=0., mtemp=0., wind=0., pres=0., hum=0.; + int ctr, status, statuses[5] = {0,0,0,0,0}; + char s_time[32]; + monit_d data; + printf("Content-type: text/plain; charset=koi8-r\n\n"); + printf("OT - %s\nIT - %s\nMT - %s\nWS - %s\nP - %s\nH - %s\nS - %s\n\n", + _L(_s_Otemp_), _L(_s_Itemp_), _L(_s_Mtemp_), + _L(_s_WSpeed_), _L(_s_Pressure_), _L(_s_Humidity_), + _L(_s_State_)); + printf("%s\t\tOT\tIT\tMT\tWS\tP\tH\tS\n", _L(_s_Date_)); + while(read(out_fd, &data, sizeof(data))){ + if(data.seconds < t_start) continue; + if(data.seconds > t_end) break; + if(!(stat_mask & (1 << data.status))) continue; + if(t_first == 0) t_first = t_last = data.seconds; + else if((data.seconds - t_first) >= aver_interval){ // накопили достаточно данных + t_first = t_first/2 + t_last/2; // середина временного интервала + ltime = *localtime(&t_first);//*localtime(&t_first); + strftime(s_time, 32, "%d/%m/%Y, %H:%M:%S", <ime); + if(ii == 0) ii = 1; + ctr = 0; + for(j = 0; j<5; j++){ + if(statuses[j] > ctr){ + ctr = statuses[j]; + status = j; + } + statuses[j] = 0; + } + printf("%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d\n", + s_time, + otemp/ii, + itemp/ii, + mtemp/ii, + wind/ii, + pres/ii, + hum/ii, + status); + t_first = data.seconds; + otemp=itemp=mtemp=wind=pres=hum=0.; + ii = 0; + } + t_last = data.seconds; + otemp += data.outdoor_temp; + itemp += data.indoor_temp; + mtemp += data.mirror_temp; + wind += data.wind_speed; + pres += data.pressure; + hum += data.humidity; + statuses[data.status]++; + ii++; + } +} + +void fill_forms(const char* alert_message, const char S_flag){ + int shmid, i = 0; + char tmp[16]; + unsigned char mask; + int im_ht = 600; + if(S_flag == 0){ + printf(Content_type); + if(alert_message) printf("

%s

\n", alert_message); + return; + } + if(get_qs_param(qs, "Stat", tmp, 16)) + mask = atoi(tmp); + else mask = 0xff; + if(get_qs_param(qs, "height", tmp, 16)){ + im_ht = atoi(tmp); + if(im_ht < 100 || im_ht > 800) im_ht = 600; + } + if(Graph){ + if(get_qs_param(qs, "Gtype", tmp, 16)){ + i = atoi(tmp); + if(iGIF) + i = GIF; + } + else i = GIF; + sendSVG(i, mask, im_ht); + } + else{ + if(S_flag == 2) send_data(mask); + else print_curvals(mask); + } +} + +void sendSVG(const int image_type, unsigned char stat_mask, int im_height){ + FILE *plot = NULL; + char s_time[32]; + struct tm ltime; + struct timeval tv; + monit_d md, *data, *ptr; + time_t time_interval; + unsigned char Flag, Comma = 0; + int twographs = 0; + char *titles[] = {"T out", "T in", "T mir", "Wind", "Pres", "Hum"}; + char *command= "/Users/eddy/bin/gnuplot"; + char *types[] = {"svg", "jpeg", "gif"}; + char *contents[] = {"svg+xml", "jpeg", "gif"}; + int f, i, j, d_len, rb; + data = calloc(1002, sizeof(monit_d)); // максимум тысяча точек + ptr = data; + printf("Content-type: image/%s\n\n", contents[image_type]); + if(Graph < 1 || Graph > 63){ + fprintf(stderr, "Graph=%d, out of range\n", Graph); + goto ret; + } + d_len = 0; + //lseek(out_fd, 0, SEEK_SET); + while(read(out_fd, &md, sizeof(md))){ +//fprintf(stderr, "time=%d, t_start=%d, t_end=%d, d_len=%d, time_interval=%d\n", md.seconds, t_start, t_end, d_len, time_interval); + if(md.seconds < t_start) continue; + if(md.seconds > t_end) break; + if(d_len == 0){ + t_start = md.seconds; + time_interval = (t_end - t_start) / 300; + } + *ptr++ = md; + if(++d_len > 300) break; // лишние значения + t_start += time_interval; +//fprintf(stderr, ">>>time=%d, t_start=%d, t_end=%d, d_len=%d, time_interval=%d\n", md.seconds, t_start, t_end, d_len, time_interval); + } + close(f); + if(d_len < 3){ + fprintf(stderr, "d_len=%d, error\n", d_len); + goto ret; + } + plot = popen(command, "w"); + if(plot == NULL){ + perror("can't run gnuplot\n"); + goto ret; + } + //fprintf(plot, "set terminal %s size 800,%d font \"/usr/share/fonts/liberation/LiberationSans-Regular.ttf\"\nset xdata time\nset timefmt \"%%d/%%m-%%H:%%M\"\nset format x \"%%H:%%M\\n%%d/%%m\"\n", + fprintf(plot, "set terminal %s size 800,%d\nset xdata time\nset timefmt \"%%d/%%m-%%H:%%M\"\nset format x \"%%H:%%M\\n%%d/%%m\"\n", + types[image_type], im_height); + if((Graph & 16) && (Graph & 32)){ // присутствуют и влажность, и давление + twographs = 1; + if(Graph & 15) // есть еще данные + fprintf(plot, "set multiplot\nset origin 0,0\nset size 1,0.5\n"); + } + else if(Graph & 48){ // присутствуют только влажность, либо только давление + if(Graph & 15){ // выводим еще что-нибудь + fprintf(plot, "set ytics nomirror\nset y2tics\nset ylabel \"degr C, m/s\"\n"); + if(Graph & 16) + fprintf(plot, "set y2label \"mmHg\"\n"); // подпись для давления + else + fprintf(plot, "set y2label \"%%\"\n"); // подпись для влажности + } + } + fprintf(plot, "plot "); + for(j = 0; j < 4; j++){ + Flag = Graph & (1 << j); + if(Flag){ + if(Comma) fprintf(plot, ","); + Comma = 1; + //w l smooth csplines + fprintf(plot, " '-' using 1:2 w l lt %d title '%s'", j+1, titles[j]); + } + } + if(!twographs){ + for(j = 4; j < 6; j++){ + if(Graph & (1 << j)){ + if(Comma) fprintf(plot, ","); + Comma = 1; + fprintf(plot, " '-' using 1:2 w l axes x1y2 lt %d title '%s'", j+1, titles[j]); + } + } + } + + fprintf(plot, "\n"); + for(j = 0; j < 6; j++){ + Flag = Graph & (1 << j); + if(twographs && j > 3) break; + if(Flag){ + for(i = 0; i < d_len; i++){ + if(!(stat_mask & (1 << data[i].status))) continue; + time_t X = (time_t)data[i].seconds; + ltime = *localtime(&X); + strftime(s_time, 32, "%d/%m-%H:%M", <ime); + fprintf(plot, "%s ", s_time); + switch(Flag){ + case 1: fprintf(plot, "%.2f\n", data[i].outdoor_temp); + break; + case 2: fprintf(plot, "%.2f\n", data[i].indoor_temp); + break; + case 4: fprintf(plot, "%.2f\n", data[i].mirror_temp); + break; + case 8: fprintf(plot, "%.2f\n", data[i].wind_speed); + break; + case 16: fprintf(plot, "%.2f\n", data[i].pressure); + break; + case 32: fprintf(plot, "%.2f\n", data[i].humidity); + break; + } + } + fprintf(plot, "e\n"); + } + } + if(twographs){ + if(Graph & 15) // строим 2 графика + fprintf(plot, "set origin 0,0.5\nset size 1,0.5\n"); + fprintf(plot, "set ylabel \"mmHg\"\nset y2label \"%%\"\n"); + fprintf(plot, "plot '-' using 1:2 w l lt 1 title 'Pres',"); + fprintf(plot, " '-' using 1:2 w l axes x1y2 lt 2 title 'Hum'\n"); + for(j = 0; j < 2; j++){ + for(i = 0; i < d_len; i++){ + if(!(stat_mask & (1 << data[i].status))) continue; + time_t X = (time_t)data[i].seconds; + ltime = *localtime(&X); + strftime(s_time, 32, "%d/%m-%H:%M", <ime); + fprintf(plot, "%s ", s_time); + switch(j){ + case 0: fprintf(plot, "%.2f\n", data[i].pressure); break; + case 1: fprintf(plot, "%.2f\n", data[i].humidity); break; + } + } + fprintf(plot, "e\n"); + } + } +ret: + if(plot){ + fflush(plot); + pclose(plot); + } + free(data); +} + +void find_starting_pos(){ // ищем в кэше смещение для начала поиска + int cache_fd; + Cache cache; + if((cache_fd = open(CACHE_FILE, O_RDONLY)) < 0){ + printf(Content_type); + printf("

%s

", _L(_s_Cant_open_cache_)); + exit(1); + } + while(read(cache_fd, &cache, sizeof(cache))){ + if(cache.time < t_start) + starting_pos = cache.offset; + else break; + } + close(cache_fd); +} + +void quit(int status){ + if(buf) free(buf); + if(out_fd) close(out_fd); + exit(status); +} + +char *switch_names(int i, char* ss){ + switch(i){ + case 0: ss = _L(_s_Otemp_); break; + case 1: ss = _L(_s_Itemp_); break; + case 2: ss = _L(_s_Mtemp_); break; + case 3: ss = _L(_s_WSpeed_); break; + case 4: ss = _L(_s_Pressure_); break; + case 5: + default: ss = _L(_s_Humidity_); + } + return ss; +} + +char *format_time(time_t t, char *ss, int i){ + struct timeval tv; + struct tm ltime = *localtime(&t); + strftime(ss, i, "%d/%m/%Y, %H:%M", <ime); + return ss; +} + +void print_string(time_t t1, time_t t2, int i){ + char s_t1[32], s_t2[32], *ss; + printf("%s - %s (%s)
\n", format_time(t1, s_t1, 32), + format_time(t2, s_t2, 32), switch_names(i, ss)); +} + +void show_extremums(int ch){ + int stat_mask = 0xFF, i, AndOr = 0, memsize, counter, first; + char tmp[32], g = 0, l = 0, *ss; + monit_d data; + float Greater, Less; + float extr[6], *meds[6]={NULL, NULL, NULL, NULL, NULL, NULL}; // экстремумы, медианы + struct timeval tv; + struct tm ltime; + time_t t1[6], t2[6], t_first=0, t_last=0; + + printf(Content_type); + if(get_qs_param(qs, "Stat", tmp, 16)) + stat_mask = atoi(tmp); + if(stat_mask == 0) stat_mask = 0xFF; + if(get_qs_param(qs, "Graph", tmp, 16)) + Graph = atoi(tmp); + if(Graph == 0) Graph = 63; + if(ch == 3){ // получение данных и проверка их корректности + if(get_qs_param(qs, "AndOr", tmp, 16)) + AndOr = atoi(tmp); + if((AndOr & 1) != AndOr) AndOr = 0; + if(get_qs_param(qs, "Greater", tmp, 32)){ + Greater = atof(tmp); + g = 1; + } + if(get_qs_param(qs, "Less", tmp, 32)){ + Less = atof(tmp); + l = 1; + } + if(!(g | l) || // нет ни Greater, ни Less + (AndOr && !(g & l)) // указано "И", но не хватает данных + ){ + printf("

%s

\n", _L(_s_No_Data_)); + return; + } + if(AndOr){ + if(Greater >= Less){ + printf("

%s

\n", _L(_s_G_mustbe_less_L_)); + return; + } + } + else{ + if((g & l) && (Greater <= Less)){ + printf("

%s

\n", _L(_s_L_mustbe_less_G_)); + return; + } + } + } + if(aver_interval < 60) aver_interval = 60; // медианное усреднение по крайней мере за минуту + switch(ch){ + case 0: ss = _L(_s_Modes_); break; + case 1: ss = _L(_s_Max_data_); break; + case 2: ss = _L(_s_Min_data_); break; + case 3: + default: ss = _L(_s_Diapazon_); + } + printf("

%s ", ss); + if(ch == 3){ + if(g){ + printf("%s %.1f ", _L(_s_Gtr_), Greater); + if(AndOr) printf("%s ", _L(_s_And_)); + else if(l) printf("%s ", _L(_s_Or_)); + } + if(l) printf("%s %.1f", _L(_s_Less_), Less); + } + printf("

\n"); + memsize = aver_interval / TIMEINTERVAL + 3; + if(ch) for(i = 0; i < 6; i++) + if(Graph & (1<\n", format_time(t_last, tmp, 32)); + t_first = 0; + } + continue; + } + if(ch == 0){ // оценка временнЫх интервалов + if(t_first == 0) t_first = t_last = data.seconds; + continue; + } + if(t_first == 0) t_first = t_last = data.seconds; + else if((data.seconds - t_first) >= aver_interval || counter > memsize || data.seconds > t_end){ + t_first = t_first/2 + t_last/2; // середина временного интервала + for(i=0; i<6; i++) + if(Graph & (1< extr[i]){ + extr[i] = meds[i][0]; + t1[i] = t_first; + } + } + else{ // ch = 2 - ищем минимумы + if(meds[i][0] < extr[i]){ + extr[i] = meds[i][0]; + t1[i] = t_first; + } + } + } + } + else{ // ищем периоды (ch == 3) + for(i=0; i<6; i++) + if(Graph & (1< Greater && meds[i][0] < Less) + if(t1[i] == 0) t1[i] = t2[i] = t_first; + else t2[i] = t_first; + else if(t1[i] != 0){ + print_string(t1[i], t2[i], i); + t1[i] = 0; + } + } + else{ // вариант с "или" + if( (g && meds[i][0] > Greater) || (l && meds[i][0] < Less) ) + if(t1[i] == 0) t1[i] = t2[i] = t_first; + else t2[i] = t_first; + else if(t1[i] != 0){ // выводим данные + print_string(t1[i], t2[i], i); + t1[i] = 0; + } + } + } + } + t_first = data.seconds; + counter = 0; + } + if(data.seconds > t_end) break; + t_last = data.seconds; + if(Graph & 1) meds[0][counter] = data.outdoor_temp; + if(Graph & 2) meds[1][counter] = data.indoor_temp; + if(Graph & 4) meds[2][counter] = data.mirror_temp; + if(Graph & 8) meds[3][counter] = data.wind_speed; + if(Graph & 16) meds[4][counter] = data.pressure; + if(Graph & 32) meds[5][counter] = data.humidity; + counter++; + } + if(ch == 1 || ch == 2) + for(i=0; i<6; i++){ + if(Graph & (1<\n", format_time(t1[i], tmp, 32), + switch_names(i, ss), extr[i]); + } + if(ch == 0){ + printf("

%s

\n", _L(_s_Mode_Times_)); + inline void fmtprnt(char **str, time_t tm){ + printf("%s: %d %s (%.2f %s)
\n", _L(str), tm, _L(_s_seconds_), + ((float)tm)/86400., _L(_s_days_)); + } + fmtprnt(_s_Stopped_, t1[0]); + fmtprnt(_s_Guiding_, t1[1]); + fmtprnt(_s_Ready_, t1[2]); + fmtprnt(_s_Other_, t1[3]); + fmtprnt(_s_Vopen_, t1[4]); + fmtprnt(_s_Total_, t1[5]); + } + for(i=0; i<6; i++) if(meds[i]) free(meds[i]); +} + +int main(){ + char *ptr, tmp[128]; + setbuf(stdout, NULL); + buf = (char*)calloc(MAX_QUERY_SIZE, 1); + ptr = getenv("HTTP_ACCEPT_LANGUAGE"); + if(ptr) if(strncmp(ptr, "ru", 2) == 0) Lang = 0; // используем русский + qs = get_qs(buf, MAX_QUERY_SIZE); + if(!qs){ + fill_forms(_L(_s_no_QS_), 0); + quit(0); + } + if(get_qs_param(qs, "Visor", tmp, 128)){ // открываем/закрываем забрало + int shmid, param = atoi(tmp); + shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0666); + printf(Content_type); + if(shmid < 0) printf(_L(_s_noVisor_)); + else{ + Visor = (int*) shmat(shmid, NULL, 0); + if(Visor){ + if(param > 0) *Visor = !(*Visor); // param >0 - смена состояния + } + else printf(_L(_s_noVisor_)); + } + printf("%s:
%s

%s:
", _L(_s_CurVstat_), + *Visor?"green":"red", *Visor?_L(_s_Vopen_):_L(_s_Vclose_), _L(_s_ChVstat_)); + printf("", *Visor ? _L(_s_Vclose_) : _L(_s_Vopen_) ); + quit(0); + } + if(!get_qs_param(qs, "Tstart", tmp, 128)){ + if(!get_qs_param(qs, "Graph", tmp, 16)) + fill_forms(_L(_s_no_tstart_), 0); + quit(0); + } + t_start = atoi(tmp); + if(get_qs_param(qs, "Tend", tmp, 128)) + t_end = atoi(tmp); + else + t_end = time(NULL); + if(t_end <= t_start){ + if(!get_qs_param(qs, "Graph", tmp, 16)) + fill_forms(_L(_s_Bad_date_), 0); + quit(1); + } + if(get_qs_param(qs, "Aver", tmp, 128)){ + aver_interval = atoi(tmp); + if(aver_interval < 1) aver_interval = 1; + } + find_starting_pos(); + if((out_fd = open(OUT_FILE, O_RDONLY)) < 0){ + exit(1); + } + lseek(out_fd, starting_pos, SEEK_SET); + if(get_qs_param(qs, "Select", tmp, 16)){ + int choice = atoi(tmp); + if(choice < 0 || choice > 3){ + fill_forms(NULL, 1); + quit(0); + } + show_extremums(choice); + quit(0); + } + if(get_qs_param(qs, "Graph", tmp, 16)){ + Graph = atoi(tmp); + if(Graph == 0) Graph = -1; + fill_forms(NULL, 1); + quit(0); + } + if(get_qs_param(qs, "Save", tmp, 16)){ + fill_forms(NULL, 2); // сохранить данные + quit(0); + } + else{ + fill_forms(NULL, 1); // показать экстремальные значения + quit(0); + } + quit(0); +} + diff --git a/C/daemon/client_cli.c b/C/daemon/client_cli.c new file mode 100644 index 0000000..6aba22e --- /dev/null +++ b/C/daemon/client_cli.c @@ -0,0 +1,328 @@ +// client.c +// +// Copyright 2012 Edward V. Emelianoff +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. + + +#define __CLIENT_C__ +#include +#include +#include +#include +#include "defines.h" +#include "lang.h" + +#define Julian(x) ((double)x/86400. + 2440587.5) + +extern const char *__progname; + +char *db_path = A_PATH; +off_t starting_pos = 0LL; +typedef struct shm_data shm_d; +unsigned char Lang = 1; // английский +time_t t_start = 0, t_end = 0; +time_t aver_interval = 1; +int force_dbpath = 0; +int out_fd; + +inline void minmax(float *min, float *max, float param){ + if(param > *max) *max = param; + else if(param < *min) *min = param; +} + +void send_data(unsigned char stat_mask){ + int ii=0, j; + struct tm ltime; + time_t t_first=0, t_last=0; + double otemp=0., itemp=0., mtemp=0., wind=0., pres=0., hum=0.; + int ctr, status, statuses[5] = {0,0,0,0,0}; + char s_time[32]; + monit_d data; + printf("OT - %s\nIT - %s\nMT - %s\nWS - %s\nP - %s\nH - %s\nS - %s\n\n", + _L(_s_Otemp_), _L(_s_Itemp_), _L(_s_Mtemp_), + _L(_s_WSpeed_), _L(_s_Pressure_), _L(_s_Humidity_), + _L(_s_State_)); + printf("%s\t\tJulian date\tOT\tIT\tMT\tWS\tP\tH\tS\n", _L(_s_Date_)); + while(read(out_fd, &data, sizeof(data)) > 0){ + time_t X = (time_t) data.seconds; + //printf("time: %zd -- %s", data.seconds, ctime(&X)); + if(X < t_start) continue; + if(X > t_end) break; + if(!(stat_mask & (1 << data.status))) continue; + if(t_first == 0) t_first = t_last = X; + else if((X - t_first) >= aver_interval){ // накопили достаточно данных + t_first = t_first/2 + t_last/2; // середина временного интервала + ltime = *localtime(&t_first);//*localtime(&t_first); + strftime(s_time, 32, "%d/%m/%Y, %H:%M:%S", <ime); + if(ii == 0) ii = 1; + ctr = 0; + for(j = 0; j<5; j++){ + if(statuses[j] > ctr){ + ctr = statuses[j]; + status = j; + } + statuses[j] = 0; + } + printf("%s\t%.6f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d\n", + s_time, + Julian(t_first), + otemp/ii, + itemp/ii, + mtemp/ii, + wind/ii, + pres/ii, + hum/ii, + status); + t_first = X; + otemp=itemp=mtemp=wind=pres=hum=0.; + ii = 0; + } + t_last = X; + otemp += data.outdoor_temp; + itemp += data.indoor_temp; + mtemp += data.mirror_temp; + wind += data.wind_speed; + pres += data.pressure; + hum += data.humidity; + statuses[data.status]++; + ii++; + } +} + +void find_starting_pos(){ // ищем в кэше смещение для начала поиска + int cache_fd; + Cache cache; + if(force_dbpath){ + char cname[256]; + snprintf(cname, 255, "%s/.cache", db_path); + cache_fd = open(cname, O_RDONLY); + }else{ + if((cache_fd = open(CACHE_FILE, O_RDONLY)) < 0) + cache_fd = open("./cache", O_RDONLY); + } + if(cache_fd < 0){ + WARN(_L(_s_Cant_open_cache_)); + exit(1); + } + while(read(cache_fd, &cache, sizeof(cache)) > 0){ + //time_t X = (time_t) cache.time; + //printf("time: %zd -- %s", cache.time, ctime(&X)); + if(cache.time < t_start) + starting_pos = cache.offset; + else break; + } + //printf("pos: %zd \n", starting_pos); + close(cache_fd); +} + +time_t get_date(char *line){ + time_t date = time(NULL); + struct tm time_, time_now; + time_now = *localtime(&date); + time_.tm_sec = 0; + if(sscanf(line, "%d/%d/%d-%d:%d", &time_.tm_mday, &time_.tm_mon, &time_.tm_year, + &time_.tm_hour, &time_.tm_min) == 5){time_.tm_mon -= 1;} + else if(!strchr(line, ':') && sscanf(line, "%d/%d/%d", &time_.tm_mday, &time_.tm_mon, &time_.tm_year) == 3){ + date = -1; time_.tm_mon -= 1;} + else if(!strchr(line, ':') && sscanf(line, "%d/%d", &time_.tm_mday, &time_.tm_mon) == 2){ + date = -1; time_.tm_mon -= 1; time_.tm_year = time_now.tm_year;} + else if(sscanf(line, "%d:%d", &time_.tm_hour, &time_.tm_min) == 2){ + time_.tm_year = time_now.tm_year; time_.tm_mon = time_now.tm_mon; + time_.tm_mday = time_now.tm_mday;} + else if(!strchr(line, ':') && !strchr(line, '/') && !strchr(line, '.') && !strchr(line, '-') + && sscanf(line, "%d", &time_.tm_mon) == 1){ + date = -1; time_.tm_mon -= 1; time_.tm_year = time_now.tm_year; + time_.tm_mday = 1;} + else{ + printf("\nWrong datetime format!\n"); + printf("Formats: D/M/Y-hh:mm, D/M/Y, hh:mm, D/M, M\n"); + exit(1); + } + if(date == -1){ + time_.tm_hour = 0; + time_.tm_min = 0; + } + if(time_.tm_mon > 11 || time_.tm_mon < 0){ + printf("\nMonth should be in 1..12\n"); + exit(2); + } + if(time_.tm_mday > 31 || time_.tm_mday < 1){ + printf("\nDate should be in 1..31, %d\n", time_.tm_mday); + exit(3); + } + if(time_.tm_year > 1900) time_.tm_year -= 1900; + else if(time_.tm_year > -1 && time_.tm_year < 100) time_.tm_year += 100; + else if(time_.tm_year < 0 || time_.tm_year > 200){ + printf("\nBad year format %d\n", time_.tm_year); + exit(4); + } + if(time_.tm_hour > 23 || time_.tm_hour < 0){ + printf("\nTime should be in 0..23\n"); + exit(5); + } + if(time_.tm_min > 59 || time_.tm_min < 0){ + printf("\nMinutes should be in 0..59\n"); + exit(6); + } + date = mktime(&time_); + return date; +} + +void print_dates(){ + char s_time[32]; + inline char *mktm(uint32_t t){ + time_t X = (time_t) t; + struct tm ltime = *localtime(&X); + strftime(s_time, 32, "%d/%m/%Y, %H:%M:%S", <ime); + return s_time; + } + monit_d data; + if(read(out_fd, &data, sizeof(data)) != sizeof(data)){ + WARN("Error reading datafile!\n"); + exit(1); + } + printf("Date of first record in database: %s\n", mktm(data.seconds)); + lseek(out_fd, -sizeof(data), SEEK_END); + if(read(out_fd, &data, sizeof(data)) != sizeof(data)){ + WARN("Error reading datafile!\n"); + exit(1); + } + printf("Date of last record in database: %s\n", mktm(data.seconds)); + exit(0); +} + +unsigned char get_modemask(const char *optarg){ + unsigned char mode = 0; + char c; + while((c = *optarg++)){ + switch (c){ + case 's': case 'S': + mode |= 1; + break; + case 'g': case 'G': + mode |= 2; + break; + case 'r': case 'R': + mode |= 4; + break; + case 'u': case 'U': + mode |= 8; + break; + case 'o': case 'O': + mode |= 16; + break; + default: + WARN("Bad mode: should be sgruo\n"); + exit(1); + } + } + return mode; +} + +void usage(char *fmt, ...){ + va_list ap; + va_start(ap, fmt); + printf("\n"); + if (fmt != NULL){ + vprintf(fmt, ap); + printf("\n\n"); + } + va_end(ap); + printf("Usage:\t%s [options]\n", + __progname); + printf("\tOptions:\n"); + printf("\t-d, --dbpath\t\tPath to database files\n"); + printf("\t-e, --tend\t\tEnding time (D/M/Y-hh:mm)\n"); + printf("\t-h, --help\t\tShow this help\n"); + printf("\t-i, --averint\t\tTime interval for data averaging (in seconds)\n"); + printf("\t-l, --lookout\t\t Show date interval of stored data\n"); + printf("\t-m, --mode\t\tTelescope mode (sgruo - Stopped, Guiding, Ready, Unknown, Opened)\n"); + printf("\t-s, --tstart\t\tStarting time (D/M/Y-hh:mm)\n"); + exit(0); +} + +int main(int argc, char **argv){ + unsigned char mask = 0; + struct option long_options[] = { + {"dbpath", 1, 0, 'd'}, + {"tend", 1, 0, 'e'}, + {"help", 0, 0, 'h'}, + {"averint", 1, 0, 'i'}, + {"lookout", 0, 0, 'l'}, + {"mode", 1, 0, 'm'}, + {"tstart", 1, 0, 's'} + }; + char short_options[] = "d:e:hi:lm:s:"; + int lookout = 0; + while (1){ + int opt; + if((opt = getopt_long(argc, argv, short_options, + long_options, NULL)) == -1) break; + switch(opt){ + case 'd': + db_path = strdup(optarg); + force_dbpath = 1; + break; + case 'e': + t_start = get_date((char*)optarg); + break; + case 'h': + usage(NULL); + break; + case 'i': + aver_interval = atoi((char*)optarg); + if(aver_interval < 1) aver_interval = 1; + break; + case 'l': + lookout = 1; + break; + case 'm': + mask = get_modemask(optarg); + break; + case 's': + t_start = get_date((char*)optarg); + break; + default: + usage("Unknown argument"); + } + } + if(argc != optind) usage("Too many arguments"); + if(t_end < 1) t_end = time(NULL); + if(t_end <= t_start){ + WARN("%s\n", _L(_s_Bad_date_)); + return(1); + } + if(mask == 0) mask = 0xff; + if(force_dbpath){ + char cname[256]; + snprintf(cname, 255, "%s/.out", db_path); + out_fd = open(cname, O_RDONLY); + }else{ + if((out_fd = open(OUT_FILE, O_RDONLY)) < 0) + out_fd = open("./out", O_RDONLY); + } + if(out_fd < 0){ + WARN(_L(_s_Cant_open_data_)); + return(1); + } + if(lookout) print_dates(); + find_starting_pos(); + lseek(out_fd, starting_pos, SEEK_SET); + send_data(mask); + return(0); +} + diff --git a/C/daemon/daemon b/C/daemon/daemon new file mode 100755 index 0000000..ac0b309 Binary files /dev/null and b/C/daemon/daemon differ diff --git a/C/daemon/daemon.c b/C/daemon/daemon.c new file mode 100644 index 0000000..56e0f49 --- /dev/null +++ b/C/daemon/daemon.c @@ -0,0 +1,312 @@ +// daemon.c - gathering info daemon +// +// Copyright 2012 Edward V. Emelianoff +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "defines.h" +#include "quick_median.c" + +uint Nth = 1 << CACHE_EVERY_PWR; // шаг по кэшированию +int MAX_DATA_LEN = 1; // длина массивов данных +int shmid; +int cache_fd, out_fd; // дескрипторы файлов кэша и выходного файла +FILE *F_log; +char TERMINATED[] = "Caught SIGTERM. Quit."; +char HUPPED[] = "Caught SIGHUP. Quit."; +char QUITTED[] = "Caught SIGQUIT. Quit."; +char INTTED[] = "Caught SIGINT. Quit."; +char STARTED[] = "Started."; +char *pidfilename = PID_FILE; + +data_type *t_out=NULL, *t_in=NULL, *t_mir=NULL, + *pres=NULL, *hum=NULL; // будущие массивы для данных + +int readname(char *name, pid_t pid){ // считать имя процесса из /proc/... + char *pp = name, byte, path[256]; + int cntr = 0, file; + snprintf (path, 255, PROC_BASE "/%d/cmdline", pid); + file = open(path, O_RDONLY); + if(file == -1) return 0; // нет файла или чужой процесс + do{ // считываем имя без слешей + read(file, &byte, 1); + if (byte != '/') *pp++ = byte; + else pp = name; + } + while(byte != EOF && byte != 0 && cntr++ < 255); + name[255] = 0; + close(file); + return 1; +} + +void check4running(){ + DIR *dir; + FILE* pidfile; + struct dirent *de; + struct stat s_buf; + pid_t pid, self, run = 0; + char name[256], myname[256]; + if (!(dir = opendir(PROC_BASE))){ // открываем директорию /proc + perror(PROC_BASE); + exit(1); + } + self = getpid(); // свой идентификатор + if(stat(pidfilename, &s_buf) == 0){ // есть файл с pid'ом + pidfile = fopen(pidfilename, "r"); + fscanf(pidfile, "%d", &run); // получаем pid (возможно) запущенного процесса + fclose(pidfile); + if(readname(name, run) && strncmp(name, myname, 255) == 0){ + WARN("\nFound running process (pid=%d), exit.\n", run); + exit(0); + } + } + // файла с pid'ом нет, или там неправильная запись + readname(myname, self); // свое имя процесса + while ((de = readdir (dir)) != NULL){ // пока не дойдем до конца директории + // пропустим, если директория не указывает на процесс, или указывает на self + if (!(pid = (pid_t) atoi (de->d_name)) || pid == self) + continue; + readname(name, pid); // считываем имя процесса + if(strncmp(name, myname, 255) == 0){ // если оно совпадает с myname + WARN("\nFound running process (pid=%d), exit.\n", pid); + exit(0); + } + } + closedir(dir); + unlink(pidfilename); // пробуем удалить pidfilename + WARN("my PID: %d\n", self); + pidfile = fopen(pidfilename, "w"); + fprintf(pidfile, "%d\n", self); // записываем в pidfilename свой pid + fclose(pidfile); +} + +inline void LOG(char* thetime, char* thetext){ + fprintf(stderr, "%s\t%s\n", thetime, thetext); + fprintf(F_log, "%s\t%s\n", thetime, thetext); +} + +double dtime(){ + double ret; + struct timeval tv; + struct timezone tz; + gettimeofday(&tv, &tz); + ret = tv.tv_sec + tv.tv_usec / 1000000.; + return ret; +} + +void printdate(char *s_time){ + time_t now = time(NULL); + struct tm ltime = *localtime(&now); + strftime(s_time, 32, "%d/%m/%Y, %H:%M:%S", <ime); +} + +static void signals(int sig){ + char nowatime[32]; + char *str; + int u; + printdate(nowatime); + if(sig == SIGTERM) + str = TERMINATED; + else if(sig == SIGHUP) + str = HUPPED; + else if(sig == SIGQUIT) + str = QUITTED; + else if(sig == SIGINT) + str = INTTED; + LOG(nowatime, str); + shmctl(shmid, IPC_RMID, NULL); // удаляем сегмент *Visor + close(cache_fd); + close(out_fd); + fclose(F_log); + if(t_out) free(t_out); if(t_in) free(t_in); + if(t_mir) free(t_mir); if(pres) free(pres); + if(hum) free(hum); + u = unlink(pidfilename); + if(u == -1) perror("Can't delete PIDfile"); + exit(sig); +} + +Status current_status(){// возвращаем текущее состояние телескопа +/* + * STOP - телескоп выключен + * GUIDING - ведение + * READY - все остановлено, питание есть + * OTHER - наведение или прочее перемещение телескопа/купола + * OPEN - идут наблюдения + */ + time_t tt = time(NULL); + struct tm t_now = *localtime(&tt); + if(t_now.tm_hour > 7 && t_now.tm_hour < 18) *Visor = 0; // "закрываем" забрало днем + if(*Visor) return OPEN; // забрало открыто + if(Tel_Hardware == Hard_Off){ // варианты STOP, OTHER + if(Dome_State == D_Off) return STOP; // все выключено + return OTHER; // купол движется + } + if(Tel_State == Stopping){ // варианты READY, OTHER + if(Dome_State == D_Off) return READY; // питание есть, все остановлено + return OTHER; // купол движется + } + // варианты GUIDING, OTHER + if(Tel_Mode == Automatic) return GUIDING; // наблюдения + return OTHER; // наведение, ручная коррекция +} + +int get_data(monit_d *data){// получаем данные +/* + превышение std 30% среднего значения - возвращаем 0 + по ошибке возвращаем -1 + все нормально - возвращаем 1 +*/ + int nn = 0; + double tt; + data_type *to = t_out, *ti = t_in, *tm = t_mir, max_wnd = 0., + *p = pres, *h = hum; +// Состоянием телескопа считать последнее + tt = dtime(); + while(check_shm_block(&sdat) && (dtime() - tt < TIMEINTERVAL)){ + *to++ = val_T1; + *ti++ = val_T2; + *tm++ = val_T3; + if(val_Wnd > max_wnd) max_wnd = val_Wnd; + *p++ = Pressure; + *h++ = val_Hmd; + if(++nn == MAX_DATA_LEN) break; + usleep(100000); // опрашиваем 10 раз в секунду +// !!! на цифре 10 завязано вычисление объема памяти для calloc, если надо будет +// изменить величину паузы, необходимо и скорректировать MAX_DATA_LEN в main + } + if(!check_shm_block(&sdat)) return -1; // ошибка получения данных + data->seconds = time(NULL) - TIMEINTERVAL/2; + // вычисляем медианные показания + data->outdoor_temp = quick_select(t_out, nn); + data->indoor_temp = quick_select(t_in, nn); + data->mirror_temp = quick_select(t_mir, nn); + data->wind_speed = max_wnd; + data->pressure = quick_select(pres, nn); + data->humidity = quick_select(hum, nn); + data->status = current_status(); + return 1; +} + +void mkcache(uint *remain){ + char nowatime[32]; + off_t offset = 0; // в данном случае - off64_t, т.е. long long + Cache s_cache; + struct stat filestat; + unsigned long long cntr = 1ULL; + uint cc = 1; + monit_d data; + printdate(nowatime); + LOG(nowatime, "Making cache"); + if(read(out_fd, &data, sizeof(data)) < sizeof(data)){ + LOG(nowatime, "Corrupted out file"); + exit(1); + } + s_cache.offset = 0; + s_cache.time = data.seconds; + write(cache_fd, &s_cache, sizeof(s_cache)); + do{ + if(cc >= Nth){ + s_cache.time = data.seconds; + write(cache_fd, &s_cache, sizeof(s_cache)); + cc = 0; + } + cc++; cntr++; + s_cache.offset = tell(out_fd); + }while(read(out_fd, &data, sizeof(data)) == sizeof(data)); + *remain = cntr && (Nth - 1); + printdate(nowatime); + LOG(nowatime, "Cache is ready"); +} + +int main(int argc, char** argv){ + char nowatime[32]; + struct stat s_stat; + uint cc = Nth + 1; + int tmp; + FILE *pidfile; + monit_d data; + Cache s_cache; + check4running(); + if(!(F_log = fopen(LOG_FILE, "a"))){ + fprintf(stderr, "Can't open log file, quit\n"); + exit(1); + } + setbuf(F_log, NULL); + printdate(nowatime); + LOG(nowatime, STARTED); + if((cache_fd = open(CACHE_FILE, O_RDWR|O_CREAT, 00644)) < 0){ + LOG(nowatime, "Can't open cache file, quit"); + exit(1); + } + if((out_fd = open(OUT_FILE, O_WRONLY|O_CREAT, 00644)) < 0){ + LOG(nowatime, "Can't open out file, quit"); + exit(1); + } + if(stat(OUT_FILE, &s_stat) < 0){ + LOG(nowatime, "Can't stat out file, quit"); + exit(1); + } + if(s_stat.st_size > 0){ // если файл с данными есть, проверяем наличие записей в кэше + if(stat(CACHE_FILE, &s_stat) < 0){ + LOG(nowatime, "Can't stat cache file, quit"); + exit(1); + } + if(s_stat.st_size == 0) + mkcache(&cc); + lseek(cache_fd, 0, SEEK_END); + lseek(out_fd, 0, SEEK_END); + } + close(0); close(1); close(2); + if(fork() != 0) exit(0); + signal(SIGTERM, signals); // kill (-15) + signal(SIGHUP, SIG_IGN); // на него можно что-нибудь повесить + signal(SIGINT, signals); // ctrl+C + signal(SIGQUIT, signals); // ctrl+\ + signal(SIGTSTP, SIG_IGN); // игнорируем ctrl+Z + get_shm_block( &sdat, ClientSide); + shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0666); + Visor = (int*) shmat(shmid, NULL, 0); + MAX_DATA_LEN = ((int)(TIMEINTERVAL)) * 10 + 11; // 11 = погрешность округления + 1 про запас + t_out = (data_type*)calloc(MAX_DATA_LEN, sizeof(data_type)); + t_in = (data_type*)calloc(MAX_DATA_LEN, sizeof(data_type)); + t_mir = (data_type*)calloc(MAX_DATA_LEN, sizeof(data_type)); + pres = (data_type*)calloc(MAX_DATA_LEN, sizeof(data_type)); + hum = (data_type*)calloc(MAX_DATA_LEN, sizeof(data_type)); + while(1){ + tmp = get_data(&data); + if(tmp == 0){ + sleep(10); + continue; + } + if(tmp == -1){ + printdate(nowatime); + LOG(nowatime, "Error getting data"); + sleep(300); + continue; + } + s_cache.offset = tell(out_fd); + write(out_fd, &data, sizeof(data)); + if(++cc >= Nth){ + s_cache.time = data.seconds; + write(cache_fd, &s_cache, sizeof(s_cache)); + cc = 0; + printdate(nowatime); + LOG(nowatime, "Add cache data"); + } + } +} + diff --git a/C/daemon/datetime.css b/C/daemon/datetime.css new file mode 100644 index 0000000..723a6b4 --- /dev/null +++ b/C/daemon/datetime.css @@ -0,0 +1,145 @@ +/* form with data & time */ +.datetime { + width: 150px;} + +/* button showdate */ +.dpBtn { + width: 22px;} + +/* input for time value */ +.dpTime { + width: 80px;} + +/* the div that holds the date picker calendar */ +.dpDiv { + } + + +/* the table (within the div) that holds the date picker calendar */ +.dpTable { + font-family: Tahoma, Arial, Helvetica, sans-serif; + font-size: 12px; + text-align: center; + color: #505050; + background: #ECF5F8; + border: 0px; + width: 180px; + } + + +/* a table row that holds date numbers (either blank or 1-31) */ +.dpTR { + } + + +/* the top table row that holds the month, year, and forward/backward buttons */ +.dpTitleTR { + } + + +/* the second table row, that holds the names of days of the week (Mo, Tu, We, etc.) */ +.dpDayTR { + } + + +/* the bottom table row, that has the "This Month" and "Close" buttons */ +.dpTodayButtonTR { + } + + +/* a table cell that holds a date number (either blank or 1-31) */ +.dpTD { + border: 0px; + width: 25px; + } + + +/* a table cell that holds a highlighted day (usually either today's date or the current date field value) */ +.dpDayHighlightTD { + border: 0px; + background-color: #CCCCCC; + } + + +/* the date number table cell that the mouse pointer is currently over (you can use contrasting colors to make it apparent which cell is being hovered over) */ +.dpTDHover { + border: 0px; + font-style: oblique; + background-color: #aca998; + cursor: pointer; + color: red; + } + + +/* the table cell that holds the name of the month and the year */ +.dpTitleTD { + border: 0px; + } + +/* the table cell that holds the time */ +.dpFullTitleTD { + border: 0px; + } + +/* a table cell that holds one of the forward/backward buttons */ +.dpButtonTD { + border: 0px; + } + + +/* the table cell that holds the "This Month" or "Close" button at the bottom */ +.dpTodayButtonTD { + border: 0px; + } + + +/* a table cell that holds the names of days of the week (Mo, Tu, We, etc.) */ +.dpDayTD { + background-color: #CCCCCC; + border: 0px; + color: white; + } + + +/* additional style information for the text that indicates the month and year */ +.dpTitleText { + font-size: 12px; + color: gray; + text-align: center; + font-weight: bold; + } + + +/* additional style information for the cell that holds a highlighted day (usually either today's date or the current date field value) */ +.dpDayHighlight { + color: 4060ff; + font-weight: bold; + } + + +/* the forward/backward buttons at the top */ +.dpButton { + font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif; + font-size: 6pt; + background: #8FCADB; + padding: 2px; + width: 20pt; + border: 0px solid #64A6B9; + color: white; + font-weight: bold; + margin-bottom: 1px; + } + + +/* the "This Month" and "Close" buttons at the bottom */ +.dpTodayButton { + font-family: Arial, Verdana, Tahoma, Helvetica, sans-serif; + font-size: 10px; + color: white; + background: #8FCADB; + font-weight: bold; + border: 0px solid #64A6B9; + padding: 1px 3px 1px 3px; + margin-right: 3px; + } + diff --git a/C/daemon/datetime.js b/C/daemon/datetime.js new file mode 100644 index 0000000..ce6a95d --- /dev/null +++ b/C/daemon/datetime.js @@ -0,0 +1,376 @@ +var datePickerDivID = "datepicker"; +var iFrameDivID = "datepickeriframe"; + +var dayArray = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'); +var monthArray = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', + 'August', 'September', 'October', 'November', 'December'); + +var timefieldValue = null; // Содержимого поля "время" + +var defaultDateSeparator = "/"; // common values would be "/" or "." +var defaultDateFormat = "mdy" // valid values are "mdy", "dmy", and "ymd" +var dateSeparator = defaultDateSeparator; +var dateFormat = defaultDateFormat; + +function displayDatePicker(dateFieldName, displayBelowThisObject, dtFormat, dtSep) +{ + var targetDateField = document.getElementsByName(dateFieldName).item(0); + + // if we weren't told what node to display the datepicker beneath, just display it + // beneath the date field we're updating + if (!displayBelowThisObject) + displayBelowThisObject = targetDateField; + + // if a date separator character was given, update the dateSeparator variable + if (dtSep) + dateSeparator = dtSep; + else + dateSeparator = defaultDateSeparator; + + // if a date format was given, update the dateFormat variable + if (dtFormat) + dateFormat = dtFormat; + else + dateFormat = defaultDateFormat; + + var x = displayBelowThisObject.offsetLeft; + var y = displayBelowThisObject.offsetTop + displayBelowThisObject.offsetHeight ; + + // deal with elements inside tables and such + var parent = displayBelowThisObject; + while (parent.offsetParent) { + parent = parent.offsetParent; + x += parent.offsetLeft; + y += parent.offsetTop ; + } + + drawDatePicker(targetDateField, x, y); +} + + +function drawDatePicker(targetDateField, x, y) +{ + var dt = getFieldDate(targetDateField.value ); + + // the datepicker table will be drawn inside of a

with an ID defined by the + // global datePickerDivID variable. If such a div doesn't yet exist on the HTML + // document we're working with, add one. + if (!document.getElementById(datePickerDivID)) { + // don't use innerHTML to update the body, because it can cause global variables + // that are currently pointing to objects on the page to have bad references + //document.body.innerHTML += "
"; + var newNode = document.createElement("div"); + newNode.setAttribute("id", datePickerDivID); + newNode.setAttribute("class", "dpDiv"); + newNode.setAttribute("style", "visibility: hidden;"); + document.body.appendChild(newNode); + } + + // move the datepicker div to the proper x,y coordinate and toggle the visiblity + var pickerDiv = document.getElementById(datePickerDivID); + pickerDiv.style.position = "absolute"; + pickerDiv.style.left = x + "px"; + pickerDiv.style.top = y + "px"; + pickerDiv.style.visibility = (pickerDiv.style.visibility == "visible" ? "hidden" : "visible"); + pickerDiv.style.display = (pickerDiv.style.display == "block" ? "none" : "block"); + pickerDiv.style.zIndex = 10000; + + // draw the datepicker table + refreshDatePicker(targetDateField.name, dt.getFullYear(), dt.getMonth(), dt.getDate()); +} + +function getTimeString(time){ + var hourString = "00" + time.getHours(); + var minuteString = "00" + time.getMinutes(); + hourString = hourString.substring(hourString.length - 2); + minuteString = minuteString.substring(minuteString.length - 2); + var timeString = ' ' + hourString + ':' + minuteString; + return timeString; +} + +// Fill time field with current time +function getTimeInput(){ + var str = "time: " + return str; +} + +/** +This is the function that actually draws the datepicker calendar. +*/ +function refreshDatePicker(dateFieldName, year, month, day) +{ + // if no arguments are passed, use today's date; otherwise, month and year + // are required (if a day is passed, it will be highlighted later) + var thisDay = new Date(); + + if ((month >= 0) && (year > 0)) { + thisDay = new Date(year, month, 1); + } else { + day = thisDay.getDate(); + thisDay.setDate(1); + } + + // the calendar will be drawn as a table + // you can customize the table elements with a global CSS style sheet, + // or by hardcoding style and formatting elements below + var crlf = "\r\n"; + var TABLE = "" + crlf; + var xTABLE = "
" + crlf; + var TR = ""; + var TR_title = ""; + var TR_days = ""; + var TR_todaybutton = ""; + var xTR = "" + crlf; + var TD = "' + getButtonCode(dateFieldName, thisDay, -1, "<","Previous month") + xTD; + html += TD_title + DIV_title + monthArray[ thisDay.getMonth()] + " " + thisDay.getFullYear() + xDIV + xTD; + html += TD_buttons + getButtonCode(dateFieldName, thisDay, 12, ">>", "Next year") + '
' + getButtonCode(dateFieldName, thisDay, 1, ">","next month") + xTD; + html += xTR; + + // this is the row that indicates which day of the week we're on + html += TR_days; + for(i = 0; i < dayArray.length; i++) + html += TD_days + dayArray[i] + xTD; + html += xTR; + + // now we'll start populating the table with days of the month + html += TR; + + // first, the leading blanks + for (i = 0; i < thisDay.getDay(); i++) + html += TD + " " + xTD; + + // now, the days of the month + do { + dayNum = thisDay.getDate(); + TD_onclick = " onclick=\"updateDateField('" + dateFieldName + "', '" + getDateString(thisDay) + "');\">"; + + if (dayNum == day) + html += TD_selected + TD_onclick + DIV_selected + dayNum + xDIV + xTD; + else + html += TD + TD_onclick + dayNum + xTD; + + // if this is a Saturday, start a new row + if (thisDay.getDay() == 6) + html += xTR + TR; + + // increment the day + thisDay.setDate(thisDay.getDate() + 1); + } while (thisDay.getDate() > 1) + + // fill in any trailing blanks + if (thisDay.getDay() > 0) { + for (i = 6; i > thisDay.getDay(); i--) + html += TD + " " + xTD; + } + html += xTR; + + // add a button to allow the user to easily return to today, or close the calendar + var today = new Date(); + html += TR_todaybutton + TD_todaybutton; + html += " "; + html += xTD + TD_buttons + xTD + TD_todaybutton; + html += ""; + html += xTD + xTR; + + // and finally, close the table + html += xTABLE; + + document.getElementById(datePickerDivID).innerHTML = html; + // add an "iFrame shim" to allow the datepicker to display above selection lists + adjustiFrame(); +} + + +/** +Convenience function for writing the code for the buttons that bring us back or forward +a month. +*/ +function getButtonCode(dateFieldName, dateVal, adjust, label, title) +{ + var newMonth = (dateVal.getMonth () + adjust) % 12; + var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12); + if (newMonth < 0) { + newMonth += 12; + newYear += -1; + } + + return ""; +} + + +/** +Convert a JavaScript Date object to a string, based on the dateFormat and dateSeparator +variables at the beginning of this script library. +*/ +function getDateString(dateVal) +{ + var dayString = "00" + dateVal.getDate(); + var monthString = "00" + (dateVal.getMonth()+1); + + dayString = dayString.substring(dayString.length - 2); + monthString = monthString.substring(monthString.length - 2); + + switch (dateFormat) { + case "dmy" : + return dayString + dateSeparator + monthString + dateSeparator + dateVal.getFullYear(); + case "ymd" : + return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString; + case "mdy" : + default : + return monthString + dateSeparator + dayString + dateSeparator + dateVal.getFullYear(); + } +} + + +/** +Convert a string to a JavaScript Date object. +*/ +function getFieldDate(dateString) +{ + var dateVal; + var dArray; + var d, m, y; + + try { + dArray = splitDateString(dateString); + if (dArray) { + switch (dateFormat) { + case "dmy" : + d = parseInt(dArray[0], 10); + m = parseInt(dArray[1], 10) - 1; + y = parseInt(dArray[2], 10); + break; + case "ymd" : + d = parseInt(dArray[2], 10); + m = parseInt(dArray[1], 10) - 1; + y = parseInt(dArray[0], 10); + break; + case "mdy" : + default : + d = parseInt(dArray[1], 10); + m = parseInt(dArray[0], 10) - 1; + y = parseInt(dArray[2], 10); + break; + } + dateVal = new Date(y, m, d); + } else if (dateString) { + dateVal = new Date(dateString); + } else { + dateVal = new Date(); + } + } catch(e) { + dateVal = new Date(); + } + return dateVal; +} + + +/** +Try to split a date string into an array of elements, using common date separators. +If the date is split, an array is returned; otherwise, we just return false. +*/ +function splitDateString(dateString) +{ + var dArray; + if (dateString.indexOf("/") >= 0) + dArray = dateString.split("/"); + else if (dateString.indexOf(".") >= 0) + dArray = dateString.split("."); + else if (dateString.indexOf("-") >= 0) + dArray = dateString.split("-"); + else if (dateString.indexOf("\\") >= 0) + dArray = dateString.split("\\"); + else + dArray = false; + + return dArray; +} + +function updateDateField(dateFieldName, dateString) +{ + var timeString = ""; + if(timefieldValue && dateString){ + var time = new Date; + time.setTime(Date.parse(dateString +' ' + timefieldValue)); + timeString = getTimeString(time); + } + + var targetDateField = document.getElementsByName(dateFieldName).item(0); + if (dateString) + targetDateField.value = dateString + timeString; + + var pickerDiv = document.getElementById(datePickerDivID); + pickerDiv.style.visibility = "hidden"; + pickerDiv.style.display = "none"; + + adjustiFrame(); + targetDateField.focus(); + + if ((dateString) && (typeof(datePickerClosed) == "function")) + datePickerClosed(targetDateField); +} + +function adjustiFrame(pickerDiv, iFrameDiv) +{ + // put a try/catch block around the whole thing, just in case + try { + if (!document.getElementById(iFrameDivID)) { + // don't use innerHTML to update the body, because it can cause global variables + // that are currently pointing to objects on the page to have bad references + //document.body.innerHTML += "