#include "mb.h" #include "cfg.h" #include "web.h" #include "lock.h" #include "list.h" #include "paras.h" #include "power.h" #include "thread.h" #include "datadef.h" #define LIMIT_HOF(x) (x*1.1f) #define LIMIT_LOF(x) (x*0.9f) typedef struct { lock_t lck; uint8_t cur_addr; uint8_t chs; //所有控制板的总通道数 power_ch_t **pch; //动态指针 power_ch_t ch0; uint8_t cnt; //实际扫到的板子个数,不可大于POWER_ uint8_t brd_max; board_data_t *pbrd[POWER_BOARD_MAX+1]; //通过modbus地址索引 board_key_t key[POWER_BOARD_MAX+1]; power_total_t ttl; uint8_t flag[POWER_CH_MAX]; product_data_t *prod; power_all_t all; }power_handle_t; static int get_power(power_ch_t *pch) { return power_get_ch(pch->info.ch, pch); } static int get_alarm(power_ch_t *pch) { power_ch_t pc; int r = power_get_ch(pch->info.ch, &pc); if(r==0) { pch->alarm = pc.alarm; } return r; } static int set_ch(power_ch_t *pch) { return power_set_ch_sw(pch->info.ch, pch->power[0].status); } static int set_open_delay(power_ch_t *pch) { return power_set_open_delay(pch); } static int set_close_delay(power_ch_t *pch) { return power_set_close_delay(pch); } static int set_kb_value(power_ch_t *pch) { return 0;//power_set_kb_val(pch); } static int set_threshold(power_ch_t *pch) { return power_set_threshold(pch); } static int reset_consump(power_ch_t *pch) { return power_reset(); } static int do_detect(uint8_t addr) { return 0; } static int get_info(uint8_t addr, board_info_t *info) { return 0; } static int get_board(board_data_t *pbrd) { return 0; } static int set_board(uint8_t addr, uint8_t on) { return power_set_board_sw(addr, on); } static int set_all(uint8_t on) { return power_set_all_sw(on); } static board_fn_t board_fn={ .get_power = get_power, .get_alarm = get_alarm, .set_ch = set_ch, .set_open_delay = set_open_delay, .set_close_delay = set_close_delay, .set_kb_value = set_kb_value, .set_threshold = set_threshold, .reset_consump = reset_consump, .detect = do_detect, .get_info = get_info, //.get_board = get_board, .set_board = set_board, .set_all = set_all, }; static power_handle_t pwrHandle={0}; static int get_flag(power_handle_t *h, uint8_t ch, uint8_t thr) { return (h->flag[ch]&(1<flag[ch] |= 1<flag[ch] &= ~(1<info.ch; ad.alarm = pch->alarm; ad.time = pch->time; web_post(PKT_TYPE_ALARM, &ad, sizeof(ad)); return 0; } static void memswap(uint8_t *buf, int len) { int i; uint8_t tmp; for(i=0; iprod->type==PDU_AC_I1O1 || h->prod->type==PDU_AC_I3O1_H) { r = read_reg(h, addr, POWER_AC_GET_INFO, tmp, 1); if(r==0) { key->type = (tmp[0]>>8)&0xFF; key->chs = tmp[0]&0xFF; } } else { r = read_reg(h, addr, POWER_DC_INFO, tmp, 2); if(r==0) { key->type = (tmp[0]>>8)&0xFF; key->chs = tmp[0]&0xFF; if(h->prod->type == PDU_AC_I3O3) { key->chs /= 3; } return 0; } } return r; } //////////////////////////////////////////////////////////////// int power_set_kb_value(power_handle_t *h, int type, int addr, kb_val_t *kv) { switch(type) { case AC_SINGLE_S_TYPE: { /* unsigned int offset = 0; unsigned int rval = 0 ; unsigned short data_temp[8] = {0}; if(chn>=8) return -1; offset = _SWITCH_AC_SINGLE_S_KB_VAL+chn*8; data_temp[0] = (unsigned short)_kb_val->voltage_k; data_temp[1] = (unsigned short)((_kb_val->voltage_k-data_temp[0])*1000); data_temp[2] = (unsigned short)_kb_val->voltage_b; data_temp[3] = (unsigned short)((_kb_val->voltage_b-data_temp[2])*1000); data_temp[4] = (unsigned short)_kb_val->current_k; data_temp[5] = (unsigned short)((_kb_val->current_k-data_temp[4])*1000); data_temp[6] = (unsigned short)_kb_val->current_b; data_temp[7] = (unsigned short)((_kb_val->current_b-data_temp[6])*1000); g_modbus_write_x_reg(manger,saddr,offset,8,data_temp); */ } break; case AC_SINGLE_B_TYPE: { /* unsigned int offset = 0; unsigned int rval = 0 ; unsigned short data_temp[8] = {0}; if(pch->info.>=4) return -1; offset = _SWITCH_AC_SINGLE_B_KB_VAL+chn*8; data_temp[0] = (unsigned short)_kb_val->voltage_k; data_temp[1] = (unsigned short)((_kb_val->voltage_k-data_temp[0])*1000); data_temp[2] = (unsigned short)_kb_val->voltage_b; data_temp[3] = (unsigned short)((_kb_val->voltage_b-data_temp[2])*1000); data_temp[4] = (unsigned short)_kb_val->current_k; data_temp[5] = (unsigned short)((_kb_val->current_k-data_temp[4])*1000); data_temp[6] = (unsigned short)_kb_val->current_b; data_temp[7] = (unsigned short)((_kb_val->current_b-data_temp[6])*1000); g_modbus_write_x_reg(manger,saddr,offset,8,data_temp); */ } break; case DCPDU_TYPE: {/* unsigned short offset = 0; unsigned short data_temp[8] = {0}; offset = _SWITCH_DC_KB_VAL; data_temp[0] = (unsigned short)_kb_val->voltage_k; data_temp[1] = (unsigned short)((_kb_val->voltage_k-data_temp[0])*1000); data_temp[2] = (unsigned short)_kb_val->voltage_b; data_temp[3] = (unsigned short)((_kb_val->voltage_b-data_temp[2])*1000); data_temp[4] = (unsigned short)_kb_val->current_k; data_temp[5] = (unsigned short)((_kb_val->current_k-data_temp[4])*1000); data_temp[6] = (unsigned short)_kb_val->current_b; data_temp[7] = (unsigned short)((_kb_val->current_b-data_temp[6])*1000); g_modbus_write_x_reg(manger,saddr,offset,8, data_temp); */ } break; case TREE_AC_TYPE: { } break; case AC_MULTI_S_TYPE: case AC_MULTI_B_TYPE: case DC_OUT_TYPE: case DC_IN_TYPE: default: return -1; } } ////////////////////////////////////////////////////////////////// static uint8_t get_ch_idx(board_data_t *pbrd, uint8_t sch) { uint8_t ch=0; uint8_t pwr_type=paras_get()->prod.type; if(pbrd->type==TREE_AC_TYPE) { if(pwr_type == PDU_AC_I3O3) { ch = pbrd->ch0 + sch/3; } else { ch = pbrd->ch0 + sch; } } else { ch = pbrd->ch0 + sch; } return ch; } static int threshold_proc(power_handle_t *h, board_data_t *pbrd) { int i,j,r=-1,times=1; power_ch_t *pch=NULL; for (i=0; ichs; i++) { pch = &pbrd->pch[i]; if(h->prod->type==PDU_AC_I3O3) { times = 3; //设置为输出三相且三相有缺失则报警 if(pch->info.ph_val && pbrd->ph_loss && get_flag(h, pch->info.ch, ALARM_PH_LOSS)==0) { set_flag(h, pch->info.ch, ALARM_PH_LOSS, 1); alarm_evt_handle(h, pch); } else { set_flag(h, pch->info.ch, ALARM_PH_LOSS, 0); } } for(j=0; jthr.v_upper.en) { if(pch->power[j].voltage>pch->thr.v_upper.val) { if(pch->alarm.v_upper && get_flag(h, pch->info.ch, ALARM_V_UPPER)==0) { set_flag(h, pch->info.ch, ALARM_V_UPPER, 1); alarm_evt_handle(h, pch); } } else if(pch->power[j].voltagethr.v_lower.val) { if(pch->alarm.v_lower && get_flag(h, pch->info.ch, ALARM_V_LOWER)==0) { set_flag(h, pch->info.ch, ALARM_V_LOWER, 1); alarm_evt_handle(h, pch); } } else { set_flag(h, pch->info.ch, ALARM_V_UPPER, 0); set_flag(h, pch->info.ch, ALARM_V_LOWER, 0); } } if(pch->thr.c_upper.en) { if(pch->power[j].current>pch->thr.c_upper.val) { if(pch->alarm.c_upper && get_flag(h, pch->info.ch, ALARM_C_UPPER)==0) { set_flag(h, pch->info.ch, ALARM_C_UPPER, 1); alarm_evt_handle(h, pch); } else { set_flag(h, pch->info.ch, ALARM_C_UPPER, 0); } } } if(pch->thr.p_upper.en) { if(pch->power[j].power>pch->thr.p_upper.val) { if(pch->alarm.p_upper && get_flag(h, pch->info.ch, ALARM_P_UPPER)==0) { set_flag(h, pch->info.ch, ALARM_P_UPPER, 0); alarm_evt_handle(h, pch); } } else { set_flag(h, pch->info.ch, ALARM_P_UPPER, 0); } } if(pch->thr.w_upper.en) { if(pch->power[j].current>pch->thr.w_upper.val) { if(pch->alarm.w_upper==1 && get_flag(h, pch->info.ch, ALARM_W_UPPER)==0) { set_flag(h, pch->info.ch, ALARM_W_UPPER, 1); alarm_evt_handle(h, pch); } } else { set_flag(h, pch->info.ch, ALARM_C_UPPER, 0); } } } } return 0; } static int total_proc(power_handle_t *h) { total_t tmp[3]={0}; int i,j,k,r=-1,times=1; power_ch_t *pch=NULL; board_data_t *pbrd=NULL; lock_on(h->lck); if(h->prod->type==PDU_AC_I3O3) times = 3; for(i=0; ibrd_max; i++) { if(h->pbrd[i]) { for (j=0; ipbrd[i]->chs; i++) { pch = &h->pbrd[i]->pch[j]; for(k=0; kpower[j].voltage; tmp[k].current += pch->power[j].current; tmp[k].power += pch->power[j].power; tmp[k].freq = pch->power[j].freq; tmp[k].consump += pch->power[j].consump; tmp[k].active = pch->power[j].active; tmp[k].reactive = pch->power[j].reactive; } } } } h->ttl.type = h->prod->type; for(k=0; kttl.total[k].voltage = tmp[k].voltage; h->ttl.total[k].current = tmp[k].current; h->ttl.total[k].power = tmp[k].power; h->ttl.total[k].freq = tmp[k].freq; h->ttl.total[k].consump = tmp[k].consump; h->ttl.total[k].factor = tmp[k].active/tmp[k].power; h->ttl.total[k].active = tmp[k].active; h->ttl.total[k].reactive = tmp[k].reactive; } lock_off(h->lck); return 0; } static int board_read(power_handle_t *h, board_data_t *pbrd) { int i,j,r=-1; power_t *pwr,power; uint16_t offset,tmp[144]; power_ch_t *pch=NULL; lock_on(h->lck); if(pbrd) { time_t tm = mktime(localtime(NULL)); switch(pbrd->type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { uint32_t val; offset = POWER_AC_CUR_INFO_L; r = read_reg(h, pbrd->addr, offset, tmp, pbrd->chs*12); if (r<0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, pbrd->chs*12); break; } for (i=0; ichs; i++) { int idx = i * 12; pwr = &pbrd->pch[i].power[0]; val = (tmp[1 + idx] << 16) | tmp[0 + idx]; pwr->voltage = val / 1000.0; val = (tmp[3 + idx] << 16) | tmp[2 + idx]; pwr->current = val / 1000.0; val = (tmp[5 + idx] << 16) | tmp[4 + idx]; pwr->power = val / 1000.0; val = (tmp[7 + idx] << 16) | tmp[6 + idx]; pwr->freq = val / 1000.0; val = (tmp[9 + idx] << 16) | tmp[8 + idx]; pwr->consump = val / 1000.0; val = (tmp[11 + idx] << 16) | tmp[10 + idx]; pwr->factor = val / 1000.0; pbrd->pch[i].time = tm; } offset = POWER_AC_STAT_INFO_L; memset(tmp,0,sizeof(tmp)); r = read_reg(h, pbrd->addr, offset, tmp, pbrd->chs); if (r<0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, pbrd->chs); break; } for (i=0; ichs; i++) { pch = &pbrd->pch[i]; pch->power[0].status = tmp[i] & (0x01); pch->alarm.v_upper = (tmp[i] & BIT(2))?1:0; pch->alarm.v_lower = (tmp[i] & BIT(4))?1:0; pch->alarm.c_upper = (tmp[i] & BIT(6))?1:0; pch->alarm.p_upper = (tmp[i] & BIT(8))?1:0; pch->alarm.w_upper = (tmp[i] & BIT(10))?1:0; pch->alarm.ph_loss = 0; } offset = POWER_AC_BREAKER_INFO; r = read_reg(h, pch->info.addr, offset, tmp, 1); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, pbrd->chs); break; } pbrd->brk[0].samp.sw = (tmp[0]&BIT(0))?1:0; pbrd->brk[0].samp.time = tm; pbrd->brk[1].samp.sw = (tmp[0]&BIT(1))?1:0; pbrd->brk[1].samp.time = tm; uint16_t buffer[16] = {0}; for (i=0; ichs; i++) { pch = &pbrd->pch[i]; offset = POWER_AC_THRESHOLD_L+i*16; r = read_reg(h, pch->info.addr, offset, buffer, 16); if(r) break; pch->thr.v_upper.val = ((buffer[1]<<16)|buffer[0])/1000; pch->thr.v_lower.val = ((buffer[3]<<16)|buffer[2])/1000; pch->thr.c_upper.val = ((buffer[5]<<16)|buffer[4])/1000; pch->thr.p_upper.val = ((buffer[9]<<16)|buffer[8])/1000; pch->thr.w_upper.val = ((buffer[13]<<16)|buffer[12])/1000; } } break; case DCPDU_TYPE: { uint32_t flag; uint16_t *ptmp = tmp + 32; offset = POWER_DC_OUT_INFO + 16; r = read_reg(h, pbrd->addr, offset, ptmp, 32); if (r<0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 32); break; } for (i = 0; i < pbrd->chs; i++) { int Index = i * 8; pwr = &pbrd->pch[i].power[0]; float value = (tmp[1 + Index] << 16) + tmp[0 + Index]; pwr->voltage = value / 1000.0; value = (tmp[3 + Index] << 16) + tmp[2 + Index]; pwr->current = value / 1000.0; value = (tmp[5 + Index] << 16) + tmp[4 + Index]; pwr->power = value / 1000.0; value = (tmp[7 + Index] << 16) + tmp[6 + Index]; pwr->consump = value / 1000.0; pwr->freq = 0; pwr->factor = 1; pbrd->pch[i].time = tm; } offset = POWER_DC_STAT_INFO; r = read_reg(h, pbrd->addr, offset, tmp, 2); if (r<0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 2); break; } for (i = 0; i < pbrd->chs; i++) { flag = (tmp[1] << 16) + tmp[0]; pbrd->pch[i].power[0].status = (flag >> i) & 0x1; } // 获取报警状态 offset = POWER_DC_WARNING; r = read_reg(h, pbrd->addr, offset, tmp, 16); if (r<0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 16); break; } for (i = 0; i < pbrd->chs; i++) { int Index = i * 2; pch = &pbrd->pch[i]; pch->alarm.v_upper = (tmp[0+Index] & BIT(0))?1:0; pch->alarm.v_lower = (tmp[0+Index] & BIT(1))?1:0; pch->alarm.c_upper = (tmp[0+Index] & BIT(2))?1:0; pch->alarm.p_upper = (tmp[0+Index] & BIT(3))?1:0; pch->alarm.w_upper = (tmp[0+Index] & BIT(4))?1:0; } } break; case TREE_AC_TYPE: { uint8_t v=0; offset = POWER_AC3_OUT_INFO; r = read_reg(h, pbrd->addr, offset, tmp, 80); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 80); break; } offset = POWER_AC3_OUT_INFO+40; uint16_t* ptmp=tmp+80; r = read_reg(h, pbrd->addr, offset, ptmp, 64); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 64); break; } for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { int index_2 = 0; for(int j = 0; j < 3;j++) { pwr = &pbrd->pch[i].power[j]; index_2 = (j*16) + (48*i); pwr->voltage = ((tmp[1+index_2] << 16) + tmp[0+index_2])/1000.0f; pwr->current = ((tmp[3+index_2] << 16) + tmp[2+index_2])/1000.0f; pwr->power = ((tmp[5+index_2] << 16) + tmp[4+index_2])/1000.0f; pwr->freq = ((tmp[11+index_2] << 16) + tmp[10+index_2])/1000.0f; pwr->consump = ((tmp[13+index_2] << 16) + tmp[12+index_2])/1000.0f; pwr->factor = ((tmp[15+index_2] << 16) + tmp[14+index_2])/1000.0f; } }else{ int Index = i * 16; pwr = &pbrd->pch[i].power[0]; float value = (tmp[1+Index] << 16) + tmp[0+Index]; pwr->voltage = value / 1000.0f; value = (tmp[3+Index] << 16) + tmp[2+Index]; pwr->current = value / 1000.0f; value = (tmp[5+Index] << 16) + tmp[4+Index]; pwr->power = value / 1000.0f; value = (tmp[7+Index] << 16) + tmp[6+Index]; value = (tmp[9+Index] << 16) + tmp[8+Index]; value = (tmp[11+Index] << 16) + tmp[10+Index]; pwr->freq = value / 1000.0f; value = (tmp[13+Index] << 16) + tmp[12+Index]; pwr->consump = value / 1000.0f; value = (tmp[15+Index] << 16) + tmp[14+Index]; pwr->factor = value / 1023.0f; pbrd->pch[i].time = tm; } } //获取通道开关状态及零线状态 offset = POWER_AC3_OUT_ENABLE; r = read_reg(h, pbrd->addr, offset, tmp, 20); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 20); break; } for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { for(int j = 0; j < 3;j++) pbrd->pch[i].power[j].status = tmp[0+(j*2)+ (i*6)] & 0x01; pbrd->pch[i].power[0].nwire = tmp[18] & 0x01; }else { int Index = i * 2; pbrd->pch[i].power[0].status = tmp[0+Index] & 0x01; pbrd->pch[i].power[0].nwire = tmp[18] & 0x01; } } //获取故障状态 offset = POWER_AC3_OUT_ERROR; r = read_reg(h, pbrd->addr, offset, tmp, 18); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, 18); break; } for (i=0; ichs; i++) { int Index = i * 2; pch = &pbrd->pch[i]; pch->alarm.v_upper = (tmp[0+Index] & BIT(0))?1:0; pch->alarm.v_lower = (tmp[0+Index] & BIT(1))?1:0; pch->alarm.c_upper = (tmp[0+Index] & BIT(2))?1:0; pch->alarm.p_upper = (tmp[0+Index] & BIT(3))?1:0; pch->alarm.w_upper = (tmp[0+Index] & BIT(4))?1:0; } offset = POWER_AC3_ALARM_MISSING_PH; r = read_reg(h, pbrd->addr, offset, tmp, pbrd->chs); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, pbrd->chs); break; } v = 0; for(i = 0; i < 3; i++) { if(tmp[i * 2]>0) { v |= 1<ph_loss = v; offset = POWER_AC3_BREAKER_INFO; r = read_reg(h, pch->info.addr, offset, tmp, 1); if (r < 0) { LOGE("read_reg failed, addr:%d reg:0x%04x/%d cnt:%d\n", pbrd->addr, offset, offset, pbrd->chs); break; } pbrd->brk[0].samp.sw = (tmp[0]&BIT(0))?1:0; pbrd->brk[0].samp.time = tm; // read v max offset = POWER_AC3_THRESHOLD_VOL_MAX; r = read_reg(h, pch->info.addr, offset, tmp, 18); for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { int Index = i * 3; int ch_idx = pbrd->ch0-1+i/3; pch = &pbrd->pch[ch_idx]; pch->thr.v_upper.val = ((tmp[Index+1] << 16) + (tmp[Index+0])) / 1000; } else { pch = &pbrd->pch[i]; pch->thr.v_upper.val = ((tmp[i+1] << 16) + (tmp[i+0])) / 1000; } } offset = POWER_AC3_THRESHOLD_VOL_MIN; r = read_reg(h, pch->info.addr, offset, tmp, 18); for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { int Index = i * 3; int ch_idx = pbrd->ch0-1+i/3; pch = &pbrd->pch[ch_idx]; pch->thr.v_lower.val = ((tmp[Index+1] << 16) + (tmp[Index+0])) / 1000; } else { pch = &pbrd->pch[i]; pch->thr.v_lower.val = ((tmp[i+1] << 16) + (tmp[i+0])) / 1000; } } offset = POWER_AC3_THRESHOLD_CUR_MAX; r = read_reg(h, pch->info.addr, offset, tmp, 18); for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { int Index = i * 3; int ch_idx = pbrd->ch0-1+i/3; pch = &pbrd->pch[ch_idx]; pch->thr.c_upper.val = ((tmp[Index+1] << 16) + (tmp[Index+0])) / 1000; } else { pch = &pbrd->pch[i]; pch->thr.c_upper.val = ((tmp[i+1] << 16) + (tmp[i+0])) / 1000; } } offset = POWER_AC3_THRESHOLD_PWR_MAX; r = read_reg(h, pch->info.addr, offset, tmp, 18); for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { int Index = i * 3; int ch_idx = pbrd->ch0-1+i/3; pch = &pbrd->pch[ch_idx]; pch->thr.p_upper.val = ((tmp[Index+1] << 16) + (tmp[Index+0])) / 1000; } else { pch = &pbrd->pch[i]; pch->thr.p_upper.val = ((tmp[i+1] << 16) + (tmp[i+0])) / 1000; } } offset = POWER_AC3_THRESHOLD_PWRCON_MAX; r = read_reg(h, pch->info.addr, offset, tmp, 18); for (i=0; ichs; i++) { if(h->prod->type==PDU_AC_I3O3) { int Index = i * 3; int ch_idx = pbrd->ch0-1+i/3; pch = &pbrd->pch[ch_idx]; pch->thr.w_upper.val = ((tmp[Index+1] << 16) + (tmp[Index+0])) / 1000; } else { pch = &pbrd->pch[i]; pch->thr.w_upper.val = ((tmp[i+1] << 16) + (tmp[i+0])) / 1000; } } } break; case AC_MULTI_S_TYPE: case AC_MULTI_B_TYPE: case DC_OUT_TYPE: case DC_IN_TYPE: default: r = -1; break; } if(r==0) { threshold_proc(h, pbrd); } } lock_off(h->lck); return r; } static int power_copy(power_handle_t *h) { int i,r=-1; power_all_t *pd=&h->all; if(h->chs>0) { if(!pd->pch || pd->chs!=h->chs) { if(pd->pch) free(pd->pch); pd->chs = 0; pd->pch = malloc(sizeof(power_ch_t)*h->chs); } if(pd->pch) { pd->chs = h->chs; for(i=0; ichs; i++) { pd->pch[i] = *h->pch[i]; } } } pd->ttl = h->ttl; return 0; } static int board_query(power_handle_t *h) { int i,r; for(i=0; ibrd_max; i++) { r = board_read(h, h->pbrd[i]); } total_proc(h); power_copy(h); return r; } static void power_thread(void *arg) { int r; board_data_t *pbrd=NULL; thread_handle_t *th=(thread_handle_t*)arg; power_handle_t *h=(power_handle_t*)th->attr->arg;; while(th->quit==0) { board_query(h); sleep(1); } } int power_init(void) { power_handle_t *h=&pwrHandle; paras_data_t *p=paras_get(); mb_para_t para={ .mode = MB_MODE_MASTER, .type = MB_TYPE_RTU, .para = { .rtu = { .dev = POWER_PORT, //设备名 .baudrate = 115200, //波特率 .parity = 0, //校验位 .pin = -1, //收发控制引脚, <0 表示不使用 .lvl = 0, //发送控制电平 } } }; memset(h, 0, sizeof(power_handle_t)); h->lck = lock_init(); h->cur_addr = 0; h->brd_max = POWER_BOARD_MAX; h->prod = &p->prod; power_scan(); thread_start(THREAD_ID_POWER, power_thread, h); return 0; } int power_deinit(void) { power_handle_t *h=&pwrHandle; lock_deinit(h->lck); return 0; } static power_ch_t* get_ch(power_handle_t *h, uint8_t ch) { if(!h->pch || !h->chs || !h->pch[ch]) { return NULL; } return h->pch[ch]; } int power_get_ch(uint8_t ch, power_ch_t *pch) { int r=-1; power_ch_t *p=NULL; power_handle_t *h=&pwrHandle; lock_on(h->lck); p = get_ch(h, ch); if(p && pch) { *pch = *p; r = 0; } lock_off(h->lck); return r; } int power_get_board(board_data_t *pbrd) { power_handle_t *h=&pwrHandle; lock_on(h->lck); if(!pbrd || !h->pch || !h->cnt || !h->pbrd[pbrd->addr]) { lock_off(h->lck); return -1; } *pbrd = *h->pbrd[pbrd->addr]; lock_off(h->lck); return 0; } int power_set(int ch, power_ch_t *pch) { power_handle_t *h=&pwrHandle; lock_on(h->lck); if(!pch || !h->pch || !h->chs || !h->pch[pch->info.ch]) { lock_off(h->lck); return -1; } *h->pch[pch->info.ch] = *pch; lock_off(h->lck); return 0; } static int power_map(power_handle_t *h, int chs) { int i,j,r,idx=1; board_data_t *pbrd=NULL; uint8_t pwr_type=paras_get()->prod.type; if(chs>0) { h->chs = 0; h->pch = (power_ch_t**)calloc(1, sizeof(power_ch_t*)*chs); if(h->pch) { h->chs = chs; h->pch[0] = &h->ch0; strcpy(h->pch[0]->info.name, "ALL"); for(i=1; i<=h->brd_max; i++) { pbrd = h->pbrd[i]; if(pbrd) { for(j=0; jchs; j++) { h->pch[idx] = &h->pbrd[i]->pch[j]; h->pch[idx]->pbrd = h->pbrd[i]; sprintf(h->pch[idx]->info.name, "CH%d", idx); idx++; } } } } } return 0; } static int power_clear(power_handle_t *h) { int i,j; memset(&h->ch0, 0, sizeof(h->ch0)); for(i=0; i<=h->brd_max; i++) { if(h->pbrd[i]) { for(j=0; jpbrd[i]->chs; j++) { if(h->pbrd[i]->pch) { free(h->pbrd[i]->pch); h->pbrd[i]->pch = NULL; } h->pbrd[i]->chs = 0; } free(h->pbrd[i]); h->pbrd[i] = NULL; } } memset(h->key, 0, sizeof(h->key)); h->cnt = 0; h->cur_addr = 0; return 0; } int power_scan(void) { int r,i,j,total_chs=1; int ch_idx=1,brd_idx=0; power_ch_t *pch=NULL; board_key_t *pkey=NULL; board_data_t *pbrd=NULL; power_handle_t *h=&pwrHandle; uint16_t times,nGroups=h->prod->ch_delay; lock_on(h->lck); power_clear(h); pch = &h->ch0; pch->info.addr = 0; pch->info.ch = 0; for(i=1; i<=h->brd_max; i++) { r = get_key(h, i, &h->key[i]); if(r==0) { LOGD("___ power_scan addr %d ok, type: %d, chs: %d\n", i, h->key[i].type, h->key[i].chs); h->cnt++; } else { LOGE("___ power_scan addr %d failed\n", i); } } for(i=1; ibrd_max; i++) { pkey = &h->key[i]; if(pkey->chs>0) { pbrd = (board_data_t*)calloc(1, sizeof(board_data_t)); if(!pbrd) { LOGE("___ power_scan, calloc pbrd %d failed\n", i); return -1; } pbrd->fn = board_fn; pbrd->type = pkey->type; pbrd->chs = pkey->chs; pbrd->addr = i; pbrd->ch0 = ch_idx; pch = (power_ch_t*)calloc(1, sizeof(power_ch_t)*pkey->chs); if(!pch) { LOGE("___ power_scan, calloc pch failed\n"); return -1; } for(j=0; jchs; j++) { pch[j].info.addr = i; pch[j].info.sch = j; //序号从0开始 pch[j].info.type = pkey->type; if(h->prod->type==PDU_AC_I3O3) { pch[j].info.ch = ch_idx+j/3; //序号从1开始, 发给控制板需从0开始 pch[j].info.ph_id = j%3; } else { pch[j].info.ch = ch_idx+j; //序号从1开始, 发给控制板需从0开始 pch[j].info.ph_id = 0; } times = (pch[j].info.ch%nGroups)?pch[j].info.ch:nGroups; pch[j].info.open_delay = 1000*times; pch[j].info.close_delay = 1000*times; } if(pbrd->type==AC_SINGLE_S_TYPE || pbrd->type==AC_SINGLE_B_TYPE) { pbrd->brk[0].info.addr = pbrd->brk[1].info.addr = pbrd->addr; } else if(pbrd->type==TREE_AC_TYPE) { pbrd->brk[0].info.addr = pbrd->addr; } if(h->prod->type==PDU_AC_I3O3) { ch_idx += pkey->chs/3; } else { ch_idx += pkey->chs; } brd_idx++; pbrd->pch = pch; h->pbrd[i] = pbrd; total_chs += pkey->chs; } } power_map(h, total_chs); lock_off(h->lck); return 0; } int power_reset(void) { int i,r=-1; uint16_t offset = 0; power_handle_t *h=&pwrHandle; board_data_t *pbrd=NULL; lock_on(h->lck); for(i=0; i<=h->brd_max; i++) { pbrd = h->pbrd[i]; if(pbrd) { switch(pbrd->type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { uint16_t tmp[8]; offset = POWER_AC_CH_STAT_L; for(i=1; i<=pbrd->chs; i++) { tmp[i] = pbrd->pch[i].power[0].status; } r = write_reg(h, pbrd->addr, offset, tmp+1, pbrd->chs-1); } break; case DCPDU_TYPE: { offset = POWER_DC_ALARM_CTRL_TOTAL; } break; case TREE_AC_TYPE: { uint16_t data_temp[20]; offset = POWER_AC3_RESET_CONSUMP; data_temp[0] = data_temp[1] = data_temp[2] = 1; r = write_reg(h, pbrd->addr, offset, data_temp, 3); if (r<0) { break; } //初始化报警阈值 uint32_t value = 0; memset(data_temp, 0, sizeof(data_temp)); offset = POWER_AC3_THRESHOLD_VOL_MAX; r = write_reg(h, pbrd->addr, offset, data_temp, 18); if (r<0) { break; } offset = POWER_AC3_THRESHOLD_VOL_MIN; r = write_reg(h, pbrd->addr, offset, data_temp, 18); if (r<0) { break; } offset = POWER_AC3_THRESHOLD_CUR_MAX; r = write_reg(h, pbrd->addr, offset, data_temp, 18); if (r<0) { break; } offset = POWER_AC3_THRESHOLD_PWR_MAX; r = write_reg(h, pbrd->addr, offset, data_temp, 18); if (r<0) { break; } offset = POWER_AC3_THRESHOLD_PWRCON_MAX; r = write_reg(h, pbrd->addr, offset, data_temp, 18); if (r<0) { break; } for (i=1; i<=pbrd->chs; i++) { memset(data_temp, 0, sizeof(data_temp)); offset = POWER_AC3_OUT_ENABLE + i; data_temp[0] = pbrd->pch[i].power[0].status; r = write_reg(h, pbrd->addr, offset, data_temp, 2); } } break; } } } lock_off(h->lck); return r; } int power_set_ch_sw_n(power_ch_t *pch) { int r; uint16_t st= pch->power[0].status,offset,tmp[2]={0}; power_handle_t *h=&pwrHandle; lock_on(h->lck); if (pch->thr.v_upper.en == 1) st |= ENABLE_AC3_V_UP; if (pch->thr.v_lower.en == 1) st |= ENABLE_AC3_V_DOWN; if (pch->thr.c_upper.en == 1) st |= ENABLE_AC3_C_UP; if (pch->thr.p_upper.en == 1) st |= ENABLE_AC3_P_UP; if (pch->thr.w_upper.en == 1) st |= ENABLE_AC3_W_UP; switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { offset = POWER_AC_CH_STAT_L + pch->info.ch-1; tmp[0] = st; r = write_reg(h, pch->info.addr, offset, tmp, 1); } break; case DCPDU_TYPE: { uint16_t mask; offset = POWER_DC_STAT_INFO+pch->info.ch-1; mask = ~(1 << (pch->info.ch-1)); tmp[0] &= mask; tmp[0] |= (st << (pch->info.ch-1)); r = write_reg(h, pch->info.addr, offset, tmp, 2); } break; case TREE_AC_TYPE: { uint16_t reg; uint8_t type=paras_get()->prod.type; if(type==PDU_AC_I3O3 || type==PDU_AC_I3O1) { reg = POWER_AC3_CH_OUT_ENABLE; } else { reg = POWER_AC3_OUT_ENABLE; } tmp[0] = st; offset = reg+pch->info.ch-1; r = write_reg(h, pch->info.addr, offset, tmp, 2); } break; } lock_off(h->lck); } int power_set_ch_sw(uint8_t ch, uint8_t on) { int r; power_ch_t *pch; power_handle_t *h=&pwrHandle; uint16_t offset,tmp[2]={0},st=on; lock_on(h->lck); pch = get_ch(h, ch); if(!pch) { lock_off(h->lck); return -1; } if (pch->thr.v_upper.en == 1) st |= ENABLE_AC3_V_UP; if (pch->thr.v_lower.en == 1) st |= ENABLE_AC3_V_DOWN; if (pch->thr.c_upper.en == 1) st |= ENABLE_AC3_C_UP; if (pch->thr.p_upper.en == 1) st |= ENABLE_AC3_P_UP; if (pch->thr.w_upper.en == 1) st |= ENABLE_AC3_W_UP; switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { offset = POWER_AC_CH_STAT_L + pch->info.ch-1; tmp[0] = st;; r = write_reg(h, pch->info.addr, offset, tmp, 1); } break; case DCPDU_TYPE: { uint16_t mask; offset = POWER_DC_STAT_INFO+pch->info.ch-1; mask = ~(1 << (pch->info.ch-1)); tmp[0] &= mask; tmp[0] |= (st << (pch->info.ch-1)); r = write_reg(h, pch->info.addr, offset, tmp, 2); } break; case TREE_AC_TYPE: { uint16_t reg; uint8_t type=paras_get()->prod.type; if(type==PDU_AC_I3O3 || type==PDU_AC_I3O1) { reg = POWER_AC3_CH_OUT_ENABLE; } else { reg = POWER_AC3_OUT_ENABLE; } tmp[0] = st; offset = reg + +pch->info.ch-1; r = write_reg(h, pch->info.addr, offset, tmp, 2); } break; } lock_off(h->lck); return r; } int power_set_board_sw(uint8_t addr, uint8_t on) { int i,r; power_ch_t *pch; board_data_t *pbrd; power_handle_t *h=&pwrHandle; pbrd = h->pbrd[addr]; if(!pbrd) { return -1; } for(i=0; ichs; i++) { power_set_ch_sw(pbrd->pch[i].info.ch, on); } return 0; } int power_set_all_sw(uint8_t on) { int i,r; power_handle_t *h=&pwrHandle; for(i=1; i<=h->chs; i++) { power_set_ch_sw(i, on); } return 0; } int power_set_alarm(power_ch_t *pch) { int r=0; uint16_t offset = 0; uint16_t nStatus = 0; power_handle_t *h=&pwrHandle; lock_on(h->lck); switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { if (pch->info.ch==0) { offset = POWER_AC_ALARM_CTRL_TOTAL; } else { offset = POWER_AC_ALARM_CTRL + pch->info.ch-1; } } break; case DCPDU_TYPE: { if (pch->info.ch==0) { offset = POWER_DC_ALARM_CTRL_TOTAL; } else { offset = POWER_DC_ALARM_CTRL + pch->info.ch-1; } } break; case TREE_AC_TYPE: { if (pch->info.ch==0) { offset = POWER_AC3_ALARM_CTRL_TOTAL; } else { offset = POWER_AC3_ALARM_CTRL + pch->info.ch-1; } } break; default: r = -1; } if(r==0) { if(pch->thr.v_upper.act==ALARM_ACT_CLOSE_CH) nStatus |= BIT(1); if(pch->thr.v_lower.act==ALARM_ACT_CLOSE_CH) nStatus |= BIT(2); if(pch->thr.c_upper.act==ALARM_ACT_CLOSE_CH) nStatus |= BIT(0); if(pch->thr.p_upper.act==ALARM_ACT_CLOSE_CH) nStatus |= BIT(3); if(pch->thr.w_upper.act==ALARM_ACT_CLOSE_CH) nStatus |= BIT(4); r = write_reg(h, pch->info.addr, offset, &nStatus, 1); } lock_off(h->lck); return r; } int power_get_threshold(power_ch_t *pch) { int i,r=0; uint16_t offset; power_ch_t *pch2=NULL; power_handle_t *h=&pwrHandle; lock_on(h->lck); pch2 = get_ch(h, pch->info.ch); pch2->thr = pch->thr; switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { uint16_t offset = 0; uint32_t temp = 0 ; uint16_t buffer[16] = {0}; if(pch->info.ch==0) { offset = POWER_AC_TOTAL_THRESHOLD; } else { offset = POWER_AC_THRESHOLD_L+(pch->info.ch-1)*16; } r = read_reg(h, pch->info.addr, offset, buffer, 16); if(r) break; pch->thr.v_upper.val = ((buffer[1]<<16)|buffer[0])/1000; pch->thr.v_lower.val = ((buffer[3]<<16)|buffer[2])/1000; pch->thr.c_upper.val = ((buffer[5]<<16)|buffer[4])/1000; pch->thr.p_upper.val = ((buffer[9]<<16)|buffer[8])/1000; pch->thr.w_upper.val = ((buffer[13]<<16)|buffer[12])/1000; } break; case DCPDU_TYPE: { uint16_t temp[4]; uint32_t value; offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_VOL_MAX:POWER_DC_THRESHOLD_VOL_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.v_upper.val = ((temp[1]<<16)|temp[0])/1000; offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_VOL_MIN:POWER_DC_THRESHOLD_VOL_MIN; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.v_lower.val = ((temp[1]<<16)|temp[0])/1000; offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_CUR_MAX:POWER_DC_THRESHOLD_CUR_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.c_upper.val = ((temp[1]<<16)|temp[0])/1000; offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_PWR_MAX:POWER_DC_THRESHOLD_POWER_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.p_upper.val = ((temp[1]<<16)|temp[0])/1000; offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_PWRCON_MAX:POWER_DC_THRESHOLD_POWERCON_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.w_upper.val = ((temp[1]<<16)|temp[0])/1000; } break; case TREE_AC_TYPE: { uint16_t temp[4]; uint32_t value; if(pch->info.ch==0) { offset = POWER_AC3_THRESHOLD_IN; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.v_upper.val = ((temp[1]<<16)|temp[0])/1000; r = read_reg(h, pch->info.addr, offset+1, temp, 2); if(r) break; pch->thr.v_lower.val = ((temp[1]<<16)|temp[0])/1000; r = read_reg(h, pch->info.addr, offset+2, temp, 2); if(r) break; pch->thr.c_upper.val = ((temp[1]<<16)|temp[0])/1000; r = read_reg(h, pch->info.addr, offset+3, temp, 2); if(r) break; pch->thr.p_upper.val = ((temp[1]<<16)|temp[0])/1000; r = read_reg(h, pch->info.addr, offset+4, temp, 2); pch->thr.w_upper.val = ((temp[1]<<16)|temp[0])/1000; } else { offset = POWER_AC3_THRESHOLD_VOL_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.v_upper.val = ((temp[1]<<16)|temp[0])/1000; offset = POWER_AC3_THRESHOLD_VOL_MIN; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.v_lower.val = ((temp[1]<<16)|temp[0])/1000; offset = POWER_AC3_THRESHOLD_CUR_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.c_upper.val = ((temp[1]<<16)|temp[0])/1000; offset = POWER_AC3_THRESHOLD_PWR_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.p_upper.val = ((temp[1]<<16)|temp[0])/1000; offset = POWER_AC3_THRESHOLD_VOL_MAX; r = read_reg(h, pch->info.addr, offset, temp, 2); if(r) break; pch->thr.p_upper.val = ((temp[1]<<16)|temp[0])/1000; } } break; default: r = -1; break; } lock_off(h->lck); return r; } int power_set_threshold(power_ch_t *pch) { int r=0; uint16_t offset; power_ch_t *pch2=NULL; power_handle_t *h=&pwrHandle; lock_on(h->lck); pch2 = get_ch(h, pch->info.ch); pch2->thr = pch->thr; switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { uint16_t offset = 0; uint32_t data_temp = 0 ; uint16_t data_buf[16] = {0}; //电压上限 data_temp = (pch->thr.v_upper.val*1000); data_buf[0] = data_temp; data_buf[1] = data_temp>>16; //电压下限 data_temp = (pch->thr.v_lower.val*1000); data_buf[2] = data_temp; data_buf[3] = data_temp>>16; //电流上限 data_temp = (pch->thr.c_upper.val*1000); data_buf[4] = data_temp; data_buf[5] = data_temp>>16; //电流下限 data_temp = (0); data_buf[6] = data_temp; data_buf[7] = data_temp>>16; //功率上限 data_temp = (pch->thr.p_upper.val*1000); data_buf[8] = data_temp; data_buf[9] = data_temp>>16; //功率下限 data_temp = 0; data_buf[10] = data_temp; data_buf[11] = data_temp>>16; //电能上限 data_temp = (pch->thr.w_upper.val*1000); data_buf[12] = data_temp; data_buf[13] = data_temp>>16; //电能下限 data_temp = 0; data_buf[14] = data_temp; data_buf[15] = data_temp>>16; if(pch->info.ch==0) { offset = POWER_AC_TOTAL_THRESHOLD; } else { offset = POWER_AC_THRESHOLD_L+(pch->info.ch-1)*16; } r = write_reg(h, pch->info.addr, offset, data_buf, 16); if(r==0) { r = power_set_alarm(pch); } } break; case DCPDU_TYPE: { uint16_t data_temp[4]; uint32_t value; offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_VOL_MAX:POWER_DC_THRESHOLD_VOL_MAX; value = pch->thr.v_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_VOL_MIN:POWER_DC_THRESHOLD_VOL_MIN; value = pch->thr.v_lower.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_CUR_MAX:POWER_DC_THRESHOLD_CUR_MAX; value = pch->thr.c_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_PWR_MAX:POWER_DC_THRESHOLD_POWER_MAX; value = pch->thr.p_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset = (pch->info.ch==0)?POWER_DC_THRESHOLD_TOTAL_PWRCON_MAX:POWER_DC_THRESHOLD_POWERCON_MAX; value = pch->thr.w_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); if(r==0) { r = power_set_alarm(pch); } } break; case TREE_AC_TYPE: { uint16_t data_temp[4]; uint32_t value; if(pch->info.ch<0) { offset = POWER_AC3_THRESHOLD_IN; value = pch->thr.v_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); value = pch->thr.v_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset+1, data_temp, 2); value = pch->thr.c_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset+2, data_temp, 2); value = pch->thr.p_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset+3, data_temp, 2); value = pch->thr.w_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset+4, data_temp, 2); } else { offset = POWER_AC3_THRESHOLD_VOL_MAX; value = pch->thr.v_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); if(h->prod->type==PDU_AC_I3O3) { offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); } offset = POWER_AC3_THRESHOLD_VOL_MIN; value = pch->thr.v_lower.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); if(h->prod->type==PDU_AC_I3O3) { offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); } offset = POWER_AC3_THRESHOLD_CUR_MAX; value = pch->thr.c_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); if(h->prod->type==PDU_AC_I3O3) { offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); } offset = POWER_AC3_THRESHOLD_PWR_MAX; value = pch->thr.p_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); if(h->prod->type==PDU_AC_I3O3) { offset +=1;; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); } offset = POWER_AC3_THRESHOLD_PWRCON_MAX; value = pch->thr.w_upper.val * 1000; data_temp[0] = value & 0XFFFF; data_temp[1] = (value >> 16) & 0xFFFF; r = write_reg(h, pch->info.addr, offset, data_temp, 2); if(h->prod->type==PDU_AC_I3O3) { offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); offset +=1; r = write_reg(h, pch->info.addr, offset, data_temp, 2); } if(r==0) { r = power_set_alarm(pch); } } } break; default: r = -1; break; } lock_off(h->lck); return r; } int power_set_open_delay(power_ch_t *pch) { int r=-1; uint16_t tmp[2],reg,offset; power_handle_t *h=&pwrHandle; lock_on(h->lck); switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { tmp[0] = pch->info.open_delay; offset = POWER_AC_OPEN_DELAY_TIME_L+pch->info.ch-1; r = write_reg(h, pch->info.addr, offset, tmp, 1); } break; case DCPDU_TYPE: { uint32_t time=pch->info.open_delay/1000; tmp[0] = time & 0xffff; tmp[1] = (time >> 16) & 0xffff; offset = POWER_DC_SET_OPEN_DELAY+pch->info.ch-1; r = write_reg(h, pch->info.addr, offset, tmp, 2); } break; case TREE_AC_TYPE: { uint32_t time=pch->info.open_delay/1000; tmp[0] = time & 0xffff; tmp[1] = (time >> 16) & 0xffff; if(h->prod->type==PDU_AC_I3O3) { offset = POWER_AC3_OPEN_DELAY_TIME+pch->info.sch*3; r = write_reg(h, pch->info.addr, offset+0, tmp, 2); if(r) break; r = write_reg(h, pch->info.addr, offset+1, tmp, 2); if(r) break; r = write_reg(h, pch->info.addr, offset+2, tmp, 2); if(r) break; } else { offset = POWER_AC3_OPEN_DELAY_TIME+pch->info.sch; r = write_reg(h, pch->info.addr, offset, tmp, 2); } } break; case AC_MULTI_S_TYPE: case AC_MULTI_B_TYPE: case DC_OUT_TYPE: case DC_IN_TYPE: default: r = -1; } lock_off(h->lck); return r; } int power_set_close_delay(power_ch_t *pch) { int r=-1; uint16_t tmp[2],reg,offset; power_handle_t *h=&pwrHandle; lock_on(h->lck); switch(pch->info.type) { case AC_SINGLE_S_TYPE: case AC_SINGLE_B_TYPE: { tmp[0] = pch->info.close_delay; offset = POWER_AC_CLOSE_DELAY_TIME_L+pch->info.ch-1; r = write_reg(h, pch->info.addr, offset, tmp, 1); } break; case DCPDU_TYPE: { uint32_t time=pch->info.close_delay/1000; tmp[0] = time & 0xffff; tmp[1] = (time >> 16) & 0xffff; offset = POWER_DC_SET_CLOSE_DELAY+pch->info.ch-1; //r = write_reg(h, pch->info.addr, offset, tmp, 2); } break; case TREE_AC_TYPE: { uint32_t time=pch->info.close_delay/1000; if(h->prod->type==PDU_AC_I3O3) { offset = POWER_AC3_CLOSE_DELAY_TIME+pch->info.sch*3; r = write_reg(h, pch->info.addr, offset+0, tmp, 2); if(r) break; r = write_reg(h, pch->info.addr, offset+1, tmp, 2); if(r) break; r = write_reg(h, pch->info.addr, offset+2, tmp, 2); if(r) break; } else { offset = POWER_AC3_CLOSE_DELAY_TIME+pch->info.sch; r = write_reg(h, pch->info.addr, offset, tmp, 2); } } break; case AC_MULTI_S_TYPE: case AC_MULTI_B_TYPE: case DC_OUT_TYPE: case DC_IN_TYPE: default: r = -1; break; } lock_off(h->lck); return r; } int power_data_get(power_all_t *all) { power_handle_t *h=&pwrHandle; if(!all) { return -1; } *all = h->all; return 0; } int power_breaker_get(breaker_all_t *all) { int i,j,idx=0; power_handle_t *h=&pwrHandle; if(!all) { return -1; } lock_on(h->lck); all->cnt = 0; for(i=1; i<=h->cnt; i++) { if(h->pbrd[i]) { all->cnt += h->pbrd[i]->chs; } } if(all->cnt>0) { all->data = (breaker_data_t*)malloc(sizeof(breaker_data_t)*all->cnt); if(all->data) { for(i=1; i<=h->cnt; i++) { if(h->pbrd[i]) { for(j=0; j<2; j++) { if(h->pbrd[i]->brk[j].info.addr>0) { all->data[idx++] = h->pbrd[i]->brk[j]; } } } } } else { all->cnt = 0; } } lock_off(h->lck); return 0; }