📄 iec103m.cpp
字号:
#include "sc_cfg.h"
#include "common.h"
#include "class.h"
#include "extern.h"
const INT8U CIec103M::RESET_CU = 0;
const INT8U CIec103M::CALL_CLASS1 = 10;
const INT8U CIec103M::CALL_CLASS2 = 11;
const INT8U CIec103M::CALL_ALL = 7;
CIec103M::CIec103M(INT8U portno):CMasterPollingProtocol(portno)
{
FCB = NULL;
ACDFlag = NULL;
isGI = NULL;
LastCommand = NULL;
if ((FCB = new INT8U[dev_num]) == NULL) ErrorExit("FCB memory alloc error in port%d", myportno);
if ((ACDFlag = new INT8U[dev_num]) == NULL) ErrorExit("ACDFlag memory alloc error in port%d", myportno);
if ((isGI = new BOOLEAN[dev_num]) == NULL) ErrorExit("isGI memory alloc error in port%d", myportno);
if ((LastCommand = new INT8U[dev_num]) == NULL) ErrorExit("LastCommand memory alloc error in port%d", myportno);
memset(FCB, 0, dev_num);
memset(ACDFlag, 0, dev_num); // communicate
memset(isGI, TRUE, dev_num);
memset(LastCommand, RESET_CU, dev_num);
PortSet_t *pPort = GetPortSet(myportno);
SetQueryGap(4000000L / pPort->Baud); // wait data transfer
send_cycle = 0;
}
void CIec103M::PreProcess()
{
if (port_yk_info.Y_PRESET) { //yk preset
if (port_yk_info.yk_des == myportno) {
port_yk_info.Y_PRESET = FALSE;
port_yk_info.Y_CHECK = TRUE;
port_yk_info.check_result = YKROK;
return;
}
}
}
void CIec103M::master_send()
{
INT8U index = CurrentQueryAddr - DevStartAddr;
if (ACDFlag[index]) { // have class1 data
switch (LastCommand[index]) { // then call class1 data
case CALL_CLASS2:
case RESET_CU:
case CALL_ALL:
query_class1_data();
QueryStatus = QUERY;
LastCommand[index] = CALL_CLASS1;
return;
}
}
if (++CurrentQueryAddr > DevEndAddr) {
CurrentQueryAddr = DevStartAddr;
send_cycle++;
}
index = CurrentQueryAddr - DevStartAddr;
if (!isLink[index]) { // if dev failure send reset cu
reset_cu();
QueryStatus = QUERY;
ACDFlag[index] = 0;
FCB[index] = 0;
isGI[index] = FALSE;
LastCommand[index] = RESET_CU;
return;
}
if (port_yk_info.Y_EXEC) { //yk execute
if (port_yk_info.yk_des == myportno) {
port_yk_info.Y_EXEC = FALSE;
send_asdu20_yk();
QueryStatus = BOARDCAST;
return;
}
}
if (port_yk_info.Y_ESC) { //yk escape
if (port_yk_info.yk_des == myportno) {
port_yk_info.Y_ESC = FALSE;
return;
}
}
if (send_cycle >= 4000) { // per 4000 cycle call general interration
for (int i = 0; i <= dev_num; i++)
isGI[i] = TRUE;
send_cycle = 0;
}
if (send_cycle % 100 == 1) { // per 99 cycle once asdu6
send_asdu6();
send_cycle++;
QueryStatus = BOARDCAST;
return;
}
switch (isGI[index]) {
case TRUE: // general interration
isGI[index] = FALSE;
send_asdu7();
QueryStatus = QUERY;
LastCommand[index] = CALL_ALL;
break;
case FALSE: // class 2
isGI[index] = FALSE;
query_class2_data();
QueryStatus = QUERY;
LastCommand[index] = CALL_CLASS2;
break;
}
}
void CIec103M::master_receive()
{
INT8U recbuf[IEC103_RECE_BUFSIZE];
INT16U rece_len = get_com_rece_num(myportno);
if (rece_len > 255) return; // too big
if (rece_len < 5) return; // too little
get_com_rece_nbytes(recbuf, 5, myportno);
if ((recbuf[0] == 0x10) && (recbuf[4] == 0x16)
&& (checksum(&recbuf[1], 2) == recbuf[3])) {
read_com_rece_nbytes(recbuf, 5, myportno);
draw_rece_message(myportno, recbuf, 5, POLL_RECE_COLOR);
process_fixed(recbuf);
return;
}
INT16U framelen = recbuf[1] + 6;
if ((recbuf[0] == 0x68) && (recbuf[3] == 0x68) && (recbuf[1] == recbuf[2])) {
if (rece_len >= framelen) {
read_com_rece_nbytes(recbuf, rece_len, myportno);
if ((recbuf[framelen - 1] == 0x16) &&
(checksum(&recbuf[4], recbuf[1]) == recbuf[framelen - 2])) {
draw_rece_message(myportno, recbuf, framelen, POLL_RECE_COLOR);
process_var(recbuf);
}
}
}
else del_com_rece_one(myportno);
}
void CIec103M::process_fixed(INT8U *buf)
{
INT8U index = CurrentQueryAddr - DevStartAddr;
if (buf[1] & 0x20) { //acd = 1
ACDFlag[index] = 1;
}
switch (buf[1] & 0x0f) {
case 0:
if (buf[2] == CurrentQueryAddr) QueryStatus = ANSWER;
break;
case 9:
if (buf[2] == CurrentQueryAddr) QueryStatus = ANSWER;
break;
case 1:
case 11:
case 14:
case 15:
if (buf[2] == CurrentQueryAddr) QueryStatus = ANSWER;
break;
}
}
void CIec103M::process_var(INT8U *buf)
{
INT8U index = CurrentQueryAddr - DevStartAddr;
if (buf[4] & 0x20) {
ACDFlag[index] = 1;
}
if (buf[9] == CurrentQueryAddr) QueryStatus = ANSWER;
if ((buf[4] & 0x0f) == 8) {
switch (buf[6]) {
case 1: // asdu1 = time tip (single dot yx)
process_asdu1(buf);
break;
case 2: // asdu2 = relative time tip (protect infomation)
process_asdu2(buf);
break;
case 5: // asdu5 = type
break;
case 8: // asdu8 = general interration end
break;
case 9: // asdu9 = measurement II
process_asdu9(buf);
break;
case 205: // asdu205 = power data
process_asdu205(buf);
break;
}
}
}
void CIec103M::process_asdu1(INT8U *buf)
{
INT8U value = 0;
soe_record_t temp_soe;
yxbw_record_t temp_yx_bw;
sclock sclk;
INT16U temp = 0;
INT16U switch_no = 0;
YxDefine_t *pyx = NULL;
for (int i = 0; i < yx_num; i++) {
pyx = GetYxDefine(pyx_tbl[i]);
if ((buf[9] == pyx->devno) &&
(buf[10] == pyx->type) && (buf[11] == pyx->info)) {
if ((buf[12] & 0x03) == 2) value = 1; // switch close
else if ((buf[12] & 0x03) == 1) value = 0; // switch open
else continue;
yx_update_db(pyx_tbl[i], value);
if (buf[8] != 1) continue; // if yx change, go on
temp_soe.status_switch_no = pyx_tbl[i] & 0xfff;
if (value)
temp_soe.status_switch_no |= 0x8000;
else temp_soe.status_switch_no &= 0x7fff; // 0x80:0->1 0x00:1->0
GetClock(&sclk);
temp = ((buf[14] << 8) & 0xff00) + buf[13];
temp_soe.day = sclk.day;
temp_soe.hour = buf[16];
temp_soe.minute = buf[15];
temp_soe.second = temp / 1000;
temp_soe.msecond = temp % 1000;
insert_soe(&temp_soe);
switch_no = temp_soe.status_switch_no & 0xfff;
temp_yx_bw.func_code = switch_no / 32;
temp_yx_bw.yx_code[0] = dbdata.Yx[switch_no / 32 * 2];
temp_yx_bw.yx_code[1] = dbdata.Yx[switch_no / 32 * 2 + 1];
insert_yx_bw(&temp_yx_bw); // add to yx bw buffer
}
}
}
void CIec103M::process_asdu2(INT8U *buf)
{
INT8U value = 0;
soe_record_t temp_soe;
yxbw_record_t temp_yx_bw;
sclock sclk;
INT16U temp = 0;
INT16U switch_no = 0;
YxDefine_t *pyx = NULL;
for (int i = 0; i < yx_num; i++) {
pyx = GetYxDefine(pyx_tbl[i]);
if ((buf[9] == pyx->devno) &&
(buf[10] == pyx->type) && (buf[11] == pyx->info)) {
if ((buf[12] & 0x03) == 2) value = 1; // switch close
else if ((buf[12] & 0x03) == 1) value = 0; // switch open
else continue;
yx_update_db(pyx_tbl[i], value);
if (buf[8] != 1) continue; // if yx change, go on
temp_soe.status_switch_no = i & 0xfff;
if (value)
temp_soe.status_switch_no |= 0x8000;
else temp_soe.status_switch_no &= 0x7fff; // 0x80:0->1 0x00:1->0
GetClock(&sclk);
temp = ((buf[18] << 8) & 0xff00) + buf[17];
temp_soe.day = sclk.day;
temp_soe.hour = buf[20];
temp_soe.minute = buf[19];
temp_soe.second = temp / 1000;
temp_soe.msecond = temp % 1000;
insert_soe(&temp_soe);
switch_no = temp_soe.status_switch_no & 0xfff;
temp_yx_bw.func_code = switch_no / 32;
temp_yx_bw.yx_code[0] = dbdata.Yx[switch_no / 32 * 2];
temp_yx_bw.yx_code[1] = dbdata.Yx[switch_no / 32 * 2 + 1];
insert_yx_bw(&temp_yx_bw); // add to yx bw buffer
}
}
}
void CIec103M::process_asdu9(INT8U *buf)
{
INT16U value = 0;
YcDefine_t *pyc = NULL;
for (int i = 0; i < yc_num; i++) {
pyc = GetYcDefine(pyc_tbl[i]);
if ((buf[9] == pyc->devno) &&
(buf[10] == pyc->type) && (buf[11] == pyc->info)) {
if ((buf[7] & 0x7f) < pyc->order) continue;
// add yc data process here
value = buf[pyc->order * 2 + 11];
value = (value << 8) + buf[pyc->order * 2 + 10];
if (value & 0x02) continue; // incorrect yc data
value = (value >> 3) & 0x1fff;
if (value & 0x1000) value = (~value & 0xfff) | 0x800;//negative
yc_update_db(pyc_tbl[i], value);
}
}
}
void CIec103M::process_asdu205(INT8U *buf)
{
INT32U value = 0;
YmDefine_t *pym = NULL;
for (int i = 0; i < ym_num; i++) {
pym = GetYmDefine(pym_tbl[i]);
if ((buf[9] == pym->devno)
&& (buf[10] == pym->type) && (buf[11] == pym->info)) {
value = buf[15];
value = (value << 8) + buf[14];
value = (value << 8) + buf[13];
value = (value << 8) + buf[12];
if (value & 0x40000000) continue;
else ym_update_db(pym_tbl[i], value & 0xfffffff);
}
}
}
void CIec103M::query_class1_data()
{
INT8U askbuf[5];
INT8U index = CurrentQueryAddr - DevStartAddr;
askbuf[0] = 0x10;
askbuf[1] = ((FCB[index] & 0x01) << 5) | 0x5a;
askbuf[2] = CurrentQueryAddr;
askbuf[3] = checksum(&askbuf[1], 2);
askbuf[4] = 0x16;
FCB[index] = ~FCB[index];
com_transfer(myportno, 5, askbuf);
draw_send_message(myportno, askbuf, 5, POLL_SEND_COLOR);
}
void CIec103M::query_class2_data()
{
INT8U askbuf[5];
INT8U index = CurrentQueryAddr - DevStartAddr;
askbuf[0] = 0x10;
askbuf[1] = ((FCB[index] & 0x01) << 5) | 0x5b;
askbuf[2] = CurrentQueryAddr;
askbuf[3] = checksum(&askbuf[1], 2);
askbuf[4] = 0x16;
FCB[index] = ~FCB[index];
com_transfer(myportno, 5, askbuf);
draw_send_message(myportno, askbuf, 5, POLL_SEND_COLOR);
}
void CIec103M::reset_cu()
{
INT8U askbuf[5];
askbuf[0] = 0x10;
askbuf[1] = 0x40;
askbuf[2] = CurrentQueryAddr;
askbuf[3] = checksum(&askbuf[1], 2);
askbuf[4] = 0x16;
com_transfer(myportno, 5, askbuf);
draw_send_message(myportno, askbuf, 5, POLL_SEND_COLOR);
}
//boardcasting sync time
void CIec103M::send_asdu6()
{
sclock clk;
INT16U temp;
INT8U askbuf[21];
GetClock(&clk);
askbuf[0] = 0x68;
askbuf[1] = 15;
askbuf[2] = 15;
askbuf[3] = 0x68;
askbuf[4] = 0x44; //send/no confirm
askbuf[5] = 0xff; //boardcast address
askbuf[6] = 0x06; //C_SYN_TA_3
askbuf[7] = 0x81; //VSQ
askbuf[8] = 0x08; //COT
askbuf[9] = 0xff; //boardcast address
askbuf[10] = 0xff; //GLB
askbuf[11] = 0;
temp = clk.second * 1000 + clk.msecond;
askbuf[12] = temp & 0xff;
askbuf[13] = (temp >> 8) & 0xff;
askbuf[14] = clk.minute & 0xff;
askbuf[15] = clk.hour & 0xff;
askbuf[16] = ((clk.weekday & 0x00) << 5) + (clk.day & 0x1f);
askbuf[17] = clk.month & 0xff;
askbuf[18] = clk.year % 100;
askbuf[19] = checksum(&askbuf[4], 15);
askbuf[20] = 0x16;
com_transfer(myportno, 21, askbuf);
draw_send_message(myportno, askbuf, 21, POLL_SEND_COLOR);
}
// general interration
void CIec103M::send_asdu7()
{
INT8U askbuf[15];
INT8U index = CurrentQueryAddr - DevStartAddr;
askbuf[0] = 0x68;
askbuf[1] = 0x09;
askbuf[2] = 0x09;
askbuf[3] = 0x68;
askbuf[4] = 0x53 | ((FCB[index] << 5) & 0x20);
askbuf[5] = CurrentQueryAddr;
askbuf[6] = 0x07;
askbuf[7] = 0x81;
askbuf[8] = 0x09;
askbuf[9] = CurrentQueryAddr;
askbuf[10] = 0xff; //GLB
askbuf[11] = 0;
askbuf[12] = CurrentQueryAddr;
askbuf[13] = checksum(&askbuf[4], 9);
askbuf[14] = 0x16;
FCB[index] = ~FCB[index];
com_transfer(myportno, 15, askbuf);
draw_send_message(myportno, askbuf, 15, POLL_SEND_COLOR);
}
// general command yk
void CIec103M::send_asdu20_yk()
{
INT8U askbuf[16];
INT8U index = port_yk_info.dev_no - DevStartAddr;
askbuf[0] = 0x68;
askbuf[1] = 0x0a;
askbuf[2] = 0x0a;
askbuf[3] = 0x68;
askbuf[4] = 0x53 | ((FCB[index] << 5) & 0x20);
askbuf[5] = port_yk_info.dev_no;
askbuf[6] = 0x14;
askbuf[7] = 0x81;
askbuf[8] = 20;
askbuf[9] = port_yk_info.dev_no;
askbuf[10] = port_yk_info.type;
askbuf[11] = port_yk_info.yk_no;
if (port_yk_info.yk_cmd == YKCTRIP) askbuf[12] = 1; // switch open
else if (port_yk_info.yk_cmd == YKCCLOSE) askbuf[12] = 2; // switch close
else askbuf[12] = 0;
askbuf[13] = 0;
askbuf[14] = checksum(&askbuf[4], 10);
askbuf[15] = 0x16;
FCB[index] = ~FCB[index];
com_transfer(myportno, 16, askbuf);
draw_send_message(myportno, askbuf, 16, POLL_SEND_COLOR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -