// modify member info all column can be modified func (this *MemberManager) modifyMemberInfo(domain string, hid, uid int64, key string, value interface{}) error { common.CheckParam(len(key) != 0) SQL := fmt.Sprintf("UPDATE %s_home_members SET %s = ? WHERE uid = ? AND hid = ?", domain, key) stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:err[%v]", err) return err } defer stmt.Close() result, err := stmt.Exec(value, uid, hid) if err != nil { log.Errorf("execute update failed:sql[%s], err[%v]", SQL, err) return err } affect, err := result.RowsAffected() if err != nil { log.Warningf("get affected rows failed:err[%v]", err) return err } if affect < 1 { log.Warningf("check affected rows failed:domain[%s], hid[%d], uid[%d], row[%d]", domain, hid, uid, affect) return common.ErrEntryNotExist } else if affect > 1 { log.Errorf("check affected rows failed:domain[%s], hid[%d], uid[%d], row[%d]", domain, hid, uid, affect) return common.ErrUnknown } return nil }
// async send request to device and wait the response on result func (this *Connection) SendRequest(packet *common.Message, result *chan common.Message) (err error) { common.Assert(packet != nil && result != nil, "check input param failed") oldId := packet.Header.MsgId log.Infof("receive new Request from app:msgId[%d]", oldId) request := NewDeviceCtrlRequest(oldId, result) // rewrite the msg id as the connection new id packet.Header.MsgId = this.getNewRequestId() err = this.requestMap.Insert(packet.Header.MsgId, request) if err != nil { log.Warningf("check request insert failed:old[%d], new[%d]", oldId, packet.Header.MsgId) return err } log.Infof("insert the request mapping succ:mid[%d], code[%d], dest[%v], gid[%s]", packet.Header.MsgId, packet.Header.MsgCode, this.socket.RemoteAddr(), this.gid.String()) // if the dev connection closed panic will occured defer func() { packet.Header.MsgId = oldId info := recover() if info != nil { log.Warningf("the request queue is closed:err[%v]", info) err = common.ErrDeviceConnClosed } }() this.requestQueue <- *packet return nil }
// modify device info all column can be modified func (this *DeviceManager) modifyDeviceInfo(checkStatus bool, domain string, did int64, key string, value interface{}) error { common.CheckParam(len(key) != 0) var SQL string if checkStatus { SQL = fmt.Sprintf("UPDATE %s_device_info SET %s = ? WHERE did = ? AND status = %d", domain, key, ACTIVE) } else { SQL = fmt.Sprintf("UPDATE %s_device_info SET %s = ? WHERE did = ?", domain, key) } stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:err[%v]", err) return err } defer stmt.Close() result, err := stmt.Exec(value, did) if err != nil { log.Errorf("execute update failed:domain[%s], key[%s], value[%v], err[%v]", domain, key, value, err) return err } affect, err := result.RowsAffected() if err != nil { log.Warningf("get affected rows failed:err[%v]", err) return err } if affect != 1 { log.Warningf("update device info failed:domain[%s], key[%s], value[%v], err[%v]", domain, key, value, err) return common.ErrEntryNotExist } return nil }
func (this *BindingProxy) GetBindingByDid(domain string, did int64) (*BindingInfo, error) { if this.cacheOn { bind, find := this.cache.Get(domain, did) if find { return bind, nil } } SQL := fmt.Sprintf("SELECT sub_domain, device_id, bind_token, expire_time FROM %s_device_mapping WHERE did = ?", domain) stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Warningf("prepare query failed:domain[%s], did[%d], err[%v]", domain, did, err) return nil, err } defer stmt.Close() bind := NewBindingInfo() err = stmt.QueryRow(did).Scan(&bind.subDomain, &bind.deviceId, &bind.grantToken, &bind.grantTime) if err != nil { if err != sql.ErrNoRows { log.Warningf("query and parse binding info failed:domain[%s], did[%d], err[%v]", domain, did, err) } else { err = common.ErrEntryNotExist } return nil, err } bind.did = did if this.cacheOn { this.cache.Set(domain, bind) } return bind, nil }
//////////////////////////////////////////////////////////////////////////////////// // database related private interface //////////////////////////////////////////////////////////////////////////////////// func (this *HomeManager) modifyHome(domain string, hid int64, key string, value interface{}) error { SQL := fmt.Sprintf("UPDATE %s_home_info SET %s = ? WHERE hid = ?", domain, key) stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:err[%v]", err) return err } defer stmt.Close() result, err := stmt.Exec(value, hid) if err != nil { log.Errorf("execute update failed:sql[%s], err[%v]", SQL, err) return err } affect, err := result.RowsAffected() if err != nil { log.Warningf("affected rows failed:err[%v]", err) return err } if affect < 1 { log.Warningf("check affected rows failed:domain[%s], hid[%d], row[%d]", domain, hid, affect) return common.ErrAccountNotExist } else if affect > 1 { log.Errorf("check affected rows failed:domain[%s], key[%s], value[%v], hid[%d], row[%d]", domain, key, value, hid, affect) return common.ErrUnknown } return nil }
func (this *Connection) Loop(waitGroup *sync.WaitGroup) { // AFTER THIS ALL THE MESSAGE USING AES this.contex.EncryptType = common.ZC_SEC_TYPE_AES this.contex.SessionKey = this.sessionKey // process write queue in the new routine waitGroup.Add(1) go func() { // request packet var requestPacket common.Message for !this.exit { select { case requestPacket = <-this.requestQueue: // write the packet to read queue fmt.Println("[DEV] send the new Request Message to device:", requestPacket.Header.MsgId) err := common.Send(this.socket, this.contex, &requestPacket, common.DEV_WRITE_TIMEOUT) if err != nil { log.Warningf("forward the packet failed:err[%v]", err) this.exit = true break } // wait the empty response for the requestPacket // if not wait empty succ, can not send the next request // from the requestQueue.... this.waitEmptyResponse(&requestPacket) fmt.Println("[DEV] wait Empty Response succ:", requestPacket.Header.MsgId) } } log.Infof("forward device request routine exit:dest[%v]", this.socket.RemoteAddr()) waitGroup.Done() }() // process the read empty or response or report message var devMessage common.Message for !this.exit { // read the packet and dispatch to the processor err := common.Receive(this.socket, this.contex, &devMessage, common.DEV_READ_TIMEOUT) if err != nil { log.Warningf("read the packet failed:dest[%v], err[%v]", this.socket.RemoteAddr(), err) this.exit = true break } fmt.Println("[DEV] Receive message from device succ", devMessage.Header.String()) // TODO if too long not receive dev message, close it // Handle Dev Message three different type // repsonse Ack + response Empty + request Report // WARNING:can not blocked here... this.handleDevMessage(&devMessage) fmt.Println("[DEV] Handle dev message finish:", time.Now().UTC(), devMessage.Header, this.socket.RemoteAddr()) } log.Infof("device routine exit succ:dest[%v], gid[%s]", this.socket.RemoteAddr(), this.gid.String()) }
//////////////////////////////////////////////////////////////////////////////////////////// /// DEVICE MANAGER //////////////////////////////////////////////////////////////////////////////////////////// // list all devices of one home func (this *DeviceManagerHandler) handleListDevices(req *zc.ZMsg, resp *zc.ZMsg) { domain := req.GetString("domain") hid := req.GetInt("hid") list, err := this.device.GetAllDevices(domain, hid) if err != nil { resp.SetErr(err.Error()) log.Warningf("list all home devices failed:domain[%s], hid[%d], err[%v]", domain, hid, err) return } for _, device := range list { resp.AddObject("devices", zc.ZObject{"id": device.GetDid(), "hid": device.GetHid(), "name": device.GetDeviceName(), "master": device.GetMasterDid()}) } log.Warningf("list all home devices succ:domain[%s], hid[%d], count[%d]", domain, hid, len(list)) resp.SetAck() }
//////////////////////////////////////////////////////////////////////////////////////////// /// HOME MANAGER //////////////////////////////////////////////////////////////////////////////////////////// // list all homes func (this *HomeManagerHandler) handleListHomes(req *zc.ZMsg, resp *zc.ZMsg) { domain := req.GetString("domain") uid := req.GetInt("uid") list, err := this.home.GetAllHome(domain, uid) if err != nil { resp.SetErr(err.Error()) log.Warningf("list all home failed:domain[%s], uid[%d], err[%v]", domain, uid, err) return } for _, home := range list { resp.AddObject("homes", zc.ZObject{"id": home.GetHid(), "name": home.GetName()}) } log.Warningf("list all home succ:domain[%s], uid[%d], count[%d]", domain, uid, len(list)) resp.SetAck() }
func (this *HomeManager) ModifyName(domain string, hid int64, name string) error { common.CheckParam(this.store != nil) home, err := this.Get(domain, hid) if err != nil { log.Warningf("get home failed:domain[%s], hid[%d], err[%v]", domain, home, err) return err } else if home == nil { log.Warningf("home not exist:domain[%s], hid[%d]", domain, hid) return common.ErrEntryNotExist } else if home.GetStatus() != ACTIVE { log.Warningf("home is not active:domain[%s], hid[%d]", domain, hid) return common.ErrInvalidStatus } return this.modifyHome(domain, hid, "name", name) }
// if find the record return basic info + nil, if not exist, return nil + nil func (this *DeviceWarehouse) Get(domain, subDomain, deviceId string) (*BasicInfo, error) { device, err := this.proxy.GetDeviceInfo(domain, subDomain, deviceId) if err != nil { log.Warningf("get device info failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return nil, err } else if device == nil { log.Warningf("not find the device info:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return nil, nil } if !device.Validate() { log.Errorf("validate device info failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return nil, common.ErrInvalidDevice } return device, nil }
func (this *WarehouseProxy) InsertDeviceInfo(domain, subDomain, deviceId, publicKey string, master bool) error { var SQL string if master { SQL = fmt.Sprintf("INSERT INTO %s_device_warehouse(sub_domain, device_id, device_type, public_key, status) VALUES(?,?,?,?,?)", domain) } else { SQL = fmt.Sprintf("INSERT INTO %s_device_warehouse(sub_domain, device_id, device_type, status) VALUES(?,?,?,?)", domain) } stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:err[%v]", err) return err } defer stmt.Close() if master { _, err = stmt.Exec(subDomain, deviceId, MASTER, publicKey, ACTIVE) } else { _, err = stmt.Exec(subDomain, deviceId, NORMAL, ACTIVE) } if err != nil { log.Warningf("execute insert device[%s:%s] failed:domain[%s], err[%v]", subDomain, deviceId, domain, err) return err } if this.cacheOn { this.cache.Delete(domain, subDomain, deviceId) } return nil }
// if not find in database return nil + nil func (this *WarehouseProxy) GetDeviceInfo(domain, subDomain, deviceId string) (*BasicInfo, error) { if this.cacheOn { basic, find := this.cache.Get(domain, subDomain, deviceId) if find { log.Infof("get device basic info from cache:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return basic, nil } } SQL := fmt.Sprintf("SELECT device_type, public_key, status FROM %s_device_warehouse WHERE sub_domain = ? AND device_id = ?", domain) stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:err[%v]", err) return nil, err } defer stmt.Close() basic := NewBasicInfo() err = stmt.QueryRow(subDomain, deviceId).Scan(&basic.deviceType, &basic.publicKey, &basic.status) if err != nil { if err == sql.ErrNoRows { log.Warningf("no find the device:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return nil, nil } log.Errorf("query failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return nil, err } basic.subDomain = subDomain basic.deviceId = deviceId if this.cacheOn { this.cache.Set(domain, basic) } return basic, nil }
// get all homes created by uid or uid as a member func (this *MemberManager) getMemberAllHomes(domain string, uid int64) ([]int64, error) { SQL := fmt.Sprintf("SELECT hid FROM %s_home_members WHERE uid = ?", domain) stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:domain[%s], uid[%d], err[%v]", domain, uid, err) return nil, err } defer stmt.Close() rows, err := stmt.Query(uid) if err != nil { log.Errorf("query all homes failed:domain[%s], uid[%d], err[%v]", domain, uid, err) return nil, err } var hid int64 list := make([]int64, 0) for rows.Next() { err = rows.Scan(&hid) if err != nil { log.Warningf("parse the result failed:domain[%s], uid[%d], err[%v]", domain, uid, err) return nil, err } list = append(list, hid) } return list, nil }
// handle device response message forward to the result channel func (this *Connection) handleDevResponse(packet *common.Message) { request, find := this.requestMap.Find(packet.Header.MsgId) if find { // reset to the old message id packet.Header.MsgId = request.(*DeviceCtrlRequest).oldMessageId defer func() { info := recover() if info != nil { log.Warningf("the response queue is closed:err[%v]", info) } _, exist := this.requestMap.Delete(packet.Header.MsgId) if !exist { log.Errorf("delete request failed:mid[%d], code[%d], dest[%s], gid[%s]", packet.Header.MsgId, packet.Header.MsgCode, this.socket.RemoteAddr(), this.gid.String()) } log.Infof("delete the request mapping succ:mid[%d], code[%d], dest[%s], gid[%s]", packet.Header.MsgId, packet.Header.MsgCode, this.socket.RemoteAddr(), this.gid.String()) }() // if closed will panic *(request.(*DeviceCtrlRequest).responseQueue) <- *packet } else { log.Errorf("check the dev response not find request:mid[%d], code[%d], dest[%s], gid[%s]", packet.Header.MsgId, packet.Header.MsgCode, this.socket.RemoteAddr(), this.gid.String()) } }
func (this *BindingProxy) IsBindingExist(domain string, did int64, exist *bool) error { if this.cacheOn { _, find := this.cache.Get(domain, did) if find { *exist = true return nil } } SQL := fmt.Sprintf("SELECT did FROM %s_device_mapping WHERE did = ?", domain) stmt, err := this.store.db.Prepare(SQL) if err != nil { log.Errorf("prepare query failed:domain[%s], did[%d], err[%v]", domain, did, err) return err } defer stmt.Close() var value int64 err = stmt.QueryRow(did).Scan(&value) if err != nil { if err == sql.ErrNoRows { *exist = false } else { log.Warningf("get binding info failed:domain[%s], did[%d], err[%v]", domain, did, err) return err } } *exist = true return nil }
func (this *BindingProxy) ChangeDeviceBinding(did int64, domain, subDomain, deviceId string) error { if this.cacheOn { this.cache.Delete(domain, did) } SQL1 := fmt.Sprintf("UPDATE %s_device_mapping SET sub_domain = ?, device_id = ?, bind_token = NULL WHERE did = ?", domain) stmt, err := this.store.db.Prepare(SQL1) if err != nil { log.Errorf("prepare update mapping failed:domain[%s], device[%s:%s], err[%v]", domain, subDomain, deviceId, err) return err } defer stmt.Close() result, err := stmt.Exec(subDomain, deviceId, did) if err != nil { log.Errorf("execute update failed:domain[%s], device[%s:%s], err[%v]", domain, subDomain, deviceId, err) return err } affect, err := result.RowsAffected() if err != nil { log.Warningf("get affected rows failed:err[%v]", err) return err } if affect != 1 { log.Errorf("check affected rows failed:domain[%s], device[%s:%s], err[%v]", domain, subDomain, deviceId, err) return common.ErrEntryNotExist } return nil }
// import a new device func (this *DeviceWarehouse) Register(domain, subDomain, deviceId, publicKey string, master bool) error { if len(subDomain) <= 0 || len(deviceId) <= 0 { log.Warningf("check domain[%s] device[%s:%s] failed", domain, subDomain, deviceId) return common.ErrInvalidParam } else if master && len(publicKey) <= 0 { log.Warningf("check public key length failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return common.ErrInvalidParam } err := this.proxy.InsertDeviceInfo(domain, subDomain, deviceId, publicKey, master) if err != nil { log.Warningf("insert device info failed:domain[%s], device[%s:%s], master[%t]", domain, subDomain, deviceId, master) return err } return nil }
////////////////////////////////////////////////////////////////////////////// /// public interface can not delete the binding info in normal cases ////////////////////////////////////////////////////////////////////////////// // if not exist return nil + nil func (this *BindingManager) Get(domain string, did int64) (*BindingInfo, error) { bind, err := this.proxy.GetBindingByDid(domain, did) if err != nil { log.Warningf("get binding info failed:domain[%s], did[%d], err[%v]", domain, did, err) return nil, err } return bind, nil }
// WARNING: must be cautious for using this interface // delete the device only for not online device func (this *DeviceWarehouse) Delete(domain, subDomain, deviceId string) error { err := this.proxy.DeleteDeviceInfo(domain, subDomain, deviceId) if err != nil { log.Warningf("delete the device failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return err } return nil }
func (this *DeviceWarehouseHandler) handleGetPublicKey(req *zc.ZMsg, resp *zc.ZMsg) { domain := req.GetString("domain") subDomain := req.GetString("submain") deviceId := req.GetString("deviceid") // get master public key basic, err := this.warehouse.Get(domain, subDomain, deviceId) if err != nil { resp.SetErr(err.Error()) log.Warningf("get device basic info failed:domain[%s], device[%s:%s], err[%v]", domain, subDomain, deviceId, err) return } else if basic == nil || !basic.IsMaster() { resp.SetErr(common.ErrMasterNotExist.Error()) log.Warningf("get device basic info failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return } resp.PutString("publickey", basic.PublicKey()) resp.SetAck() }
// add home owner func (this *MemberManager) AddOwner(domain, owner string, hid, uid int64) error { common.CheckParam(this.store != nil) if len(owner) <= 0 { log.Warningf("check owner name failed:domain[%s], owner[%s], uid[%d], hid[%d]", domain, owner, uid, hid) return common.ErrInvalidName } return this.addOwnerMember(domain, owner, hid, uid) }
// get all members of the home, if (hid) not exist, // return empty list, not nil + nil func (this *MemberManager) GetAllMembers(domain string, hid int64) ([]Member, error) { common.CheckParam(this.store != nil) // if home not exist, return empty list list, err := this.getAllMembers(domain, hid) if err != nil { log.Warningf("get one home all members failed:domain[%s], hid[%d], err[%v]", domain, hid, err) return nil, err } return list, nil }
// get all homeids belong to this member, if no hid return empty list func (this *MemberManager) GetAllHomeIds(domain string, uid int64) ([]int64, error) { common.CheckParam(this.store != nil) list, err := this.getMemberAllHomes(domain, uid) if err != nil { log.Warningf("get member all home ids failed:domain[%s], uid[%d], err[%v]", domain, uid, err) return nil, err } return list, nil }
// delete the home and delete all the members func (this *MemberManager) DeleteAllMembers(domain string, hid int64) error { common.CheckParam(this.store != nil) err := this.deleteAllMembers(domain, hid) if err != nil { log.Warningf("delete home all members failed:domain[%s], hid[%d], err[%s]", domain, hid, err) return err } return nil }
// create a new home func (this *HomeManager) Create(domain string, uid int64, name string) error { common.CheckParam(this.store != nil) if len(name) <= 0 { log.Warningf("check the home name failed:uid[%d], name[%s]", uid, name) return common.ErrInvalidParam } hid, err := this.insertHome(domain, uid, name) if err != nil { log.Warningf("insert home failed:domain[%s], createUid[%d], name[%s]", domain, uid, name) return err } // insert member as creator type to the home_members member := NewMemberManager(this.store) err = member.AddOwner(domain, "owner", hid, uid) if err != nil { log.Errorf("add owner to the home failed:domain[%s], createUid[%d], name[%s]", domain, uid, name) return err } return nil }
// check privelige and return the access device keys func (this *DeviceAccessPointHandler) handleGetAccessPoint(req *zc.ZMsg, resp *zc.ZMsg) { domain := req.GetString("domain") uid := req.GetInt("uid") did := req.GetInt("did") if len(domain) <= 0 || uid <= 0 || did <= 0 { resp.SetErr(common.ErrInvalidRequest.Error()) log.Warningf("check request invalid:domain[%s], uid[%d], did[%d]", domain, uid, did) return } subDomain, deviceId, err := this.accessPoint.GetAccessPoint(uid, domain, did) if err != nil { resp.SetErr(err.Error()) log.Warningf("get device ctrl access point failed:domain[%s], uid[%d], did[%d], err[%v]", domain, uid, did, err) return } resp.AddString("domain", domain) resp.AddString("submain", subDomain) resp.AddString("deviceid", deviceId) resp.SetAck() }
func (this *GatewayServiceHandler) handleForwardRequest(req *zc.ZMsg, resp *zc.ZMsg) { domain := req.GetString("domain") subDomain := req.GetString("submain") deviceId := req.GetString("deviceid") Conn, find := this.device.Find(*server.NewDeviceGID(domain, subDomain, deviceId)) if !find || Conn == nil { resp.SetErr(common.ErrDeviceForward.Error()) log.Warningf("the device gateway not find:gid[%s:%s:%s]", domain, subDomain, deviceId) return } // convert the request to message by loading by so var request common.Message request.Header.Version = 1 request.Header.MsgId = 1 request.Header.MsgCode = 123 payload, _ := req.GetPayload() request.Header.PayloadLen = uint16(len(payload)) request.Payload = payload // receive the device response result result := make(chan common.Message, 32) defer close(result) err := Conn.(*server.Connection).SendRequest(&request, &result) if err != nil { resp.SetErr(err.Error()) log.Warningf("forward message to dev failed:gid[%s:%s:%s], err[%v]", domain, subDomain, deviceId, err) return } log.Infof("forward message to device succ:code[%d], gid[%s:%s:%s]", request.Header.MsgCode, domain, subDomain, deviceId) // wait reponse from the device then response to the appclient response, err := this.waitResponse(request.Header.MsgId, result, common.APP_TIMEOUT) if err != nil { resp.SetErr(err.Error()) log.Warningf("wait the current response failed:gid[%s:%s:%s], err[%v]", domain, subDomain, deviceId, err) return } log.Infof("forward device request succ:gid[%s:%s:%s]", domain, subDomain, deviceId) resp.PutObject("response", zc.ZObject{"body": response.Payload}) resp.SetAck() }
////////////////////////////////////////////////////////////////////////////// /// public interface ////////////////////////////////////////////////////////////////////////////// // if find the record return device + nil, else if no record return nil + nil func (this *DeviceManager) Get(domain string, did int64) (*DeviceInfo, error) { var device DeviceInfo err := this.getDeviceInfo(domain, did, &device) if err != nil { if err == common.ErrEntryNotExist { return nil, nil } log.Warningf("get device info failed:domain[%s], did[%d], err[%v]", domain, did, err) return nil, err } return &device, nil }
// delete home func (this *HomeManagerHandler) handleDeleteHome(req *zc.ZMsg, resp *zc.ZMsg) { domain := req.GetString("domain") hid := req.GetInt("hid") err := this.home.Delete(domain, hid) if err != nil { resp.SetErr(err.Error()) log.Warningf("delete home failed:domain[%s], hid[%d], err[%v]", domain, hid, err) return } log.Infof("delete home succ:domain[%s], hid[%d]", domain, hid) resp.SetAck() }
// check basic device info from device warehouse // binding one device to one home, if masterDid < 0 it's master device, otherwise it's slave device func (this *BindingManager) checkDeviceInfo(domain, subDomain, deviceId string, isMaster bool) error { dev, err := this.warehouse.Get(domain, subDomain, deviceId) if err != nil { log.Warningf("get device failed:domain[%s], device[%s:%s], err[%v]", domain, subDomain, deviceId, err) return err } else if dev == nil { log.Warningf("check the device not exist:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return common.ErrInvalidDevice } else if !dev.Validate() { log.Errorf("device validate failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return common.ErrInvalidDevice } else if isMaster && dev.deviceType != MASTER { log.Warningf("check the master device type failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return common.ErrInvalidDevice } else if (!isMaster) && (dev.deviceType == MASTER) { log.Warningf("check the slave device type failed:domain[%s], device[%s:%s]", domain, subDomain, deviceId) return common.ErrInvalidDevice } return nil }