#include "cascade.h" #include "mb.h" #include "lock.h" #include "list.h" #include "modbus.h" #include #include #include "pthread.h" #include "stdio.h" #include "string.h" #include "power.h" typedef struct { uint8_t cmd; uint8_t obj; uint8_t chId; // char time_s[24]; //start time // char time_e[24]; //end time uint8_t data[200]; }cmd_data_t; typedef void * handle_t; typedef struct { mb_inst_t *h; uint8_t mode; uint8_t type; }mb_conn_t; typedef struct { mb_conn_t rtu; mb_conn_t tcp; rt_thread_t tid; uint8_t quit; handle_t rx; handle_t tx; }mb_handle_t; typedef struct { int addr; int err; //err times }slave_t; typedef struct cascade_info{ uint8_t saddr; uint8_t md_type; //void* list_ch; //cascade_slave list //cascade_data_t cas_data; slave_info_t info; lock_t lock; void* mb; slave_t slaves[CASCADE_MAX+1]; cmd_data_t cmd; union { md_ac_dc_t ac_dc; md_3_ac_t ac_3; }data; //modbus to user }cascade_handle_t; static int mb_write_read(cascade_handle_t *cas, int addr, data_t *wd, data_t *rd); static cascade_handle_t slave_info = {0}; uint8_t cascade_init(const char* uart,uint8_t mode,uint8_t addr,uint8_t baud) { list_cfg_t lc={0,LIST_FULL_FIFO,10}; mb_para_t para; para.type = MB_TYPE_RTU; para.para.rtu.dev = (char *)uart; para.para.rtu.baudrate = baud; para.para.rtu.parity = 2; para.para.rtu.pin = -1; para.para.rtu.lvl = 0; if(addr == 0){ para.mode = MB_MODE_MASTER; }else { para.mode = MB_MODE_SLAVE; slave_info.saddr = addr; } slave_info.lock = lock_d_init(); slave_info.mb = mb_init(¶); if(!slave_info.mb) { return -1; } if(para.mode == MB_MODE_SLAVE) { mb_handle_t *handle = (mb_handle_t *)(slave_info.mb); mb_set_slave(handle->rtu.h,slave_info.saddr); //mb_set_cb_table(); } //cas data return 0; } static uint8_t master_scan(cascade_handle_t *cas) { static uint8_t slave_addr = 1; if(slave_addr > CASCADE_MAX) { slave_addr = 1; } if(cas->slaves[slave_addr].addr == 0) { //scan uint16_t value = 0; lock_s_hold(cas->lock); int r = mb_read(cas->mb,slave_addr,CASCADE_REG_SCAN,&value,1,300); lock_s_release(cas->lock); if(r > 0) { cas->slaves[slave_addr].addr = slave_addr; cas->slaves[slave_addr].err = 0; //获取当前 } } slave_addr++; } void * cascade_scan_thread(void *arg) { while(1) { if(slave_info.md_type == MB_MODE_MASTER) { master_scan(&slave_info); } sleep(1); } } static int slave_get_info(cascade_handle_t *cas) { slave_info_t *info=&cas->info; board_all_t *board = get_control_board(); info->channels = board->chs; //info->channels=0; //memcpy(info->ch,board->pbrd[],) //copy mem to info } static void* off_on_thread(void *arg) { cascade_handle_t *cas=&slave_info; cmd_data_t *pcmd=(cmd_data_t*)arg; if(pcmd->cmd==CASCADE_CMD_OPEN) { // LOGD("____ slave CASCADE_CMD_OPEN\n"); } else { // LOGD("____ slave CASCADE_CMD_CLOSE\n"); } int flag=((pcmd->cmd==CASCADE_CMD_OPEN)?1:0); if(pcmd->chId == 0xff) { // all }else { //one } if(pcmd->cmd==CASCADE_CMD_OPEN) { // sprintf(temp,"$开启$|$所有$|$通道$"); } else { // sprintf(temp,"$关闭$|$所有$|$通道$"); } //data base free(pcmd); pthread_exit(NULL); } static int sendlen=0; void slave_func(uint16_t reg,void *r_w_data,uint32_t lenth) { cmd_data_t *cmd=NULL; mb_handle_t *handle = (mb_handle_t *)(slave_info.mb); pthread_t id = 0; switch (reg) { case CASCADE_REG_SCAN: break; case CASCADE_REG_WRITE: { cmd = (cmd_data_t*)(r_w_data); if(cmd->cmd>=CASCADE_CMD_GET_INFO) { slave_info.cmd = *cmd; } sendlen = 0; switch(cmd->cmd) { case CASCADE_CMD_OPEN: case CASCADE_CMD_CLOSE: { cmd_data_t *pcmd=malloc(sizeof(cmd_data_t)); if(pcmd) { *pcmd = *cmd; //thread_start_simp(cmd_thread, pcmd, 4*MB); //pthread_create(); pthread_create(&id,NULL,off_on_thread,pcmd); pthread_detach(id); } } break; case CASCADE_CMD_OPEN_NF: case CASCADE_CMD_CLOSE_NF: { } break; case CASCADE_CMD_SAVE: case CASCADE_CMD_SAVE3: { } break; case CASCADE_CMD_BREAKER_SAVE_ADD: { } break; case CASCADE_CMD_BREAKER_SAVE_UPDATE: { } break; case CASCADE_CMD_BREAKER_SAVE_DELETE: { } break; } } break; case CASCADE_REG_READ: { cmd = &slave_info.cmd; switch(cmd->cmd) { case CASCADE_CMD_GET_INFO: { slave_get_info(&slave_info); memcpy(r_w_data,&slave_info.info+sendlen,lenth*2); } break; case CASCADE_CMD_QUERY_CH: { slave_get_info(&slave_info); memcpy(r_w_data,&slave_info.info+sendlen,lenth*2); } break; case CASCADE_CMD_BREAKER_QUERY: break; case CASCADE_CMD_QUERY_VOL:break; case CASCADE_CMD_QUERY_CUR:break; case CASCADE_CMD_QUERY_PWR:break; case CASCADE_CMD_QUERY_PWRQ:break; case CASCADE_CMD_QUERY_HIS:break; case CASCADE_CMD_QUERY_TOTAL:break; case CASCADE_CMD_QUERY_TOTAL_PWR:break; case CASCADE_CMD_BREAKER_GET_INFO:break; } sendlen += lenth*2; } break; default: { } break; } } #define REGS(x) (((x)+(x)%2)/2) static int _mb_write(cascade_handle_t *cas, int addr, data_t *d) { int i = 0,r=0,timeout=0; int wl,xlen,wlen=0,oncelen=250; uint16_t buff[MB_BUF_SIZE]; if(d->dlen<=0) { return -1; } lock_d_hold(cas->lock); while(1) { if(wlen+oncelen>d->dlen) { xlen = d->dlen-wlen; } else { xlen = oncelen; } xlen += xlen%2; memcpy(buff, d->data+wlen, xlen); wl = mb_write(cas->mb, addr, CASCADE_REG_WRITE, buff, xlen/2); if(wl<0) { LOGE("___ _mb_write failed, addr: %d, reg: %d, cnt: %d, %s, retry: %d\n", addr, CASCADE_REG_WRITE, xlen/2,"write failed",i); r = -1; break; } if(wlen+wl*2>=d->dlen) { break; }else { xlen = wl*2; } wlen += xlen; } lock_d_release(cas->lock); } static int _mb_read(cascade_handle_t *cas, int addr, data_t *d) { int i=0,r=0,finish=0,timeout=0; int rl,xlen,rlen=0,oncelen=250; uint16_t buff[MB_BUF_SIZE]; if(d->dlen<=0) { return -1; } lock_d_hold(cas->lock); while(1) { if(rlen+oncelen>d->dlen) { xlen = d->dlen-rlen; }else{ xlen = oncelen; } xlen += xlen%2; rl = mb_read(cas->mb, addr, CASCADE_REG_READ, buff, xlen/2,500000); if(rl<0) { LOGE("___ _mb_read failed, %s, rlen: %d, retry: %d\n", "read error", rlen, i); r = -1; break; } if(rlen+rl*2>=d->dlen) { xlen = d->dlen-rlen; finish = 1; }else { xlen = rl*2; } memcpy((char*)d->data+rlen, buff, xlen); rlen += xlen; if(finish) { break; } } } static int mb_write_read(cascade_handle_t *cas, int addr, data_t *wd, data_t *rd) { int r=0; r = _mb_write(cas->mb, addr,wd); if(r==0) { r = _mb_read(cas->mb, addr,rd); } return r; } static int master_cmd(cascade_handle_t *cas,uint8_t cur_dev_addr ,cmd_data_t *cmd) { int i,r; data_t rdata,wdata; if(cur_dev_addr==0) { return -1; } switch(cmd->cmd) { case CASCADE_CMD_OPEN: case CASCADE_CMD_CLOSE: case CASCADE_CMD_SAVE: case CASCADE_CMD_SAVE3: case CASCADE_CMD_OPEN_NF: case CASCADE_CMD_CLOSE_NF: { LOGD("____ master CMD: %d\n", cmd->cmd); wdata.dlen = sizeof(cmd_data_t); wdata.data = (uint8_t*)cmd; r = _mb_write(cas, cur_dev_addr, &wdata); } break; case CASCADE_CMD_GET_INFO: { wdata.dlen = sizeof(cmd_data_t); wdata.data = (uint8_t*)cmd; rdata.dlen = sizeof(slave_info_t)-sizeof(power_ch_t)*SLAVE_CH_MAX; rdata.data = (uint8_t*)&cas->info; r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata); if(r==0) { //LOGD("______cas->info.cnt: %d\n", cas->sInfo.cnt); rdata.dlen = sizeof(slave_info_t)-sizeof(power_ch_t)*(SLAVE_CH_MAX - cas->info.channels); rdata.data = (uint8_t*)&cas->info; r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata); if(r==0) { //power_add(cas); } } else { LOGE("_____ master CASCADE_CMD_GET_INFO failed\n"); } } break; case CASCADE_CMD_BREAKER_GET_INFO: { // wdata.dlen = sizeof(cmd_data_t); // wdata.data = (uint8_t*)cmd; // rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*CH_MAX; // rdata.data = (uint8_t*)&cas->sBreaker; // LOGD("_____ master send CASCADE_CMD_BREAKER_GET_INFO\n"); // r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata); // if(r==0) { // LOGD("______cas->info.cnt: %d\n", cas->sBreaker.cnt); // rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*(CH_MAX-cas->sBreaker.cnt); // rdata.data = (uint8_t*)&cas->sBreaker; // r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata); // if(r==0) { // breaker_add(cas); // } // } } break; case CASCADE_CMD_BREAKER_SAVE_UPDATE: case CASCADE_CMD_BREAKER_SAVE_DELETE: case CASCADE_CMD_BREAKER_SAVE_ADD: { // wdata.dlen = sizeof(cmd_data_t); // wdata.data = (uint8_t*)cmd; // r = mb_write(cas, cur_dev_addr, &wdata); } break; default: cas->cmd = *cmd; r = 0; } return r; } static int master_query(cascade_handle_t *cas) { int i,r; cmd_data_t *cmd=&cas->cmd; data_t rdata,wdata; wdata.dlen = sizeof(cmd_data_t); wdata.data = (uint8_t*)cmd; switch(cmd->cmd) { case CASCADE_CMD_QUERY_CH: { //LOGD("__00__ master query CASCADE_CMD_QUERY_CH, cnt: %d\n", cas->sInfo.cnt); if(cas->info.channels==0 || cas->info.channels>SLAVE_CH_MAX) { return -1; } rdata.dlen = sizeof(slave_info_t)-sizeof(power_ch_t)*(CH_MAX-cas->info.channels); rdata.data = (uint8_t*)&cas->info; r = mb_write_read(cas, cas->saddr, &wdata, &rdata); if(r==0) { //power_update(cas); cmd->cmd = CASCADE_CMD_BREAKER_QUERY; } else { LOGE("____ master query CASCADE_CMD_QUERY_CH failed\n"); } //LOGD("__11__ master query CASCADE_CMD_QUERY_CH, cnt: %d\n", cas->sInfo.cnt); } break; case CASCADE_CMD_BREAKER_QUERY: { // wdata.dlen = sizeof(cmd_data_t); // wdata.data = (uint8_t*)cmd; // rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*CH_MAX; // rdata.data = (uint8_t*)&cas->sBreaker; // r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata); // LOGD("____ master query CASCADE_CMD_BREAKER_QUERY, cnt: %d\n", cas->sBreaker.cnt); // if(cas->sBreaker.cnt==0 || cas->sBreaker.cnt>CH_MAX) // { // breaker_clear(cas); // cmd->cmd = CASCADE_CMD_QUERY_CH; // return -1; // } // rdata.dlen = sizeof(breaker_info_t)-sizeof(breaker_channel_info_t)*(CH_MAX-cas->sBreaker.cnt); // rdata.data = (uint8_t*)&cas->sBreaker; // r = mb_write_read(cas, cur_dev_addr, &wdata, &rdata); // if(r == 0) // { // breaker_add(cas); // cmd->cmd = CASCADE_CMD_QUERY_CH; // }else // { // LOGE("____ master query CASCADE_CMD_BREAKER_QUERY failed\n"); // } } break; case CASCADE_CMD_QUERY_VOL: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; case CASCADE_CMD_QUERY_CUR: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; case CASCADE_CMD_QUERY_PWR: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; case CASCADE_CMD_QUERY_PWRQ: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; case CASCADE_CMD_QUERY_HIS: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; case CASCADE_CMD_QUERY_TOTAL: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; case CASCADE_CMD_QUERY_TOTAL_PWR: { // if(cmd->obj==OBJ_CHANNEL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else if(cmd->obj==OBJ_OVERALL) { // //rdata.dlen = sizeof(chInfo); // //rdata.data = (uint8_t*)&chInfo; // } // else { // return -1; // } } break; default: //LOGD("____ master query cmd: %d\n", cmd->cmd); return -1; } return r; } int mb_port_read_disc(u16 addr, u8 *pbit)//读离散量输入, 返回 : 0-成功, -2-地址错误 { MB_ASSERT(pbit != NULL); return(-2); } int mb_port_read_coil(u16 addr, u8 *pbit)//读线圈, 返回 : 0-成功, -2-地址错误 { MB_ASSERT(pbit != NULL); return(-2); } int mb_port_write_coil(u16 addr, u8 bit)//写线圈, 返回 : 0-成功, -2-地址错误, -4-设备故障 { return(-2); } int mb_port_read_input(u16 addr, u16 *preg)//读输入寄存器, 返回 : 0-成功, -2-地址错误 { MB_ASSERT(preg != NULL); return(-2); } int mb_port_read_hold(u16 addr, u16 *preg)//读保持寄存器, 返回 : 0-成功, -2-地址错误 { MB_ASSERT(preg != NULL); uint16_t *data = NULL; if( AC_DC_DEV_CHN_REG <= addr && addr <= AC_DC_DRY_REG) { data = (uint16_t*)(&slave_info.data.ac_dc); uint32_t offset = addr - AC_DC_DEV_CHN_REG; *preg = *(data+offset); return 0; } if(AC_3_DEV_CHN_REG <= addr && addr <= AC_3_DRY_REG) { data = (uint16_t*)(&slave_info.data.ac_3); uint32_t offset = addr - AC_DC_DEV_CHN_REG; *preg = *(data+offset); return 0; } return(-2); } int mb_port_write_hold(u16 addr, u16 reg)//写保持寄存器, 返回 : 0-成功, -2-地址错误, -3-值非法, -4-设备故障 { board_all_t *board = get_control_board(); if(AC_DC_SET_DELAY_OPEN <= addr && addr <= AC_DC_ALL_SET_SWITCH_REG) { switch(addr) { case AC_DC_SET_DELAY_OPEN ... (AC_DC_SET_DELAY_CLOSE-1): { uint16_t channel = addr - AC_DC_SET_DELAY_OPEN; //获取通道控制接口 写入数据 } break; } return 0; } return(-2); }