func TestOnboardEndnodeAppMapper_wrongPassword(t *testing.T) { mapper := newMapper() defer mapper.clear() app := common.App{ AppID: "app67890", AppKey: "app0987654321abcdefghijklmn", ServerLocation: "jp", } mapper.StateTable = &state.Table{ Gateway: state.DoneOnboard, Apps: map[common.LocalID]state.State{ common.LocalID(app.LocalID()): state.DoneOnboard, }, } mapper.cloud.err4OnboardEndnodeApp = common.ErrWrongPassword id, err := mapper.OnboardEndnodeApp(app) if err == nil { t.Fatal("should fail") } if id != "" { t.Fatal("id should be empty") } if err.Error() != "wrong password of gateway" { t.Fatal("fail with unexpected error", err) } }
func TestOnboardEndnodeAppMapper_restoringGateway(t *testing.T) { mapper := newMapper() defer mapper.clear() app := common.App{ AppID: "app67890", AppKey: "app0987654321abcdefghijklmn", ServerLocation: "jp", } restoreStates := []state.State{state.WaitingRestore, state.Restoring} for _, s := range restoreStates { mapper.StateTable = &state.Table{ Gateway: s, Apps: map[common.LocalID]state.State{ common.LocalID(app.LocalID()): state.WaitingRestore, }, RestoreMode: true, } id, err := mapper.OnboardEndnodeApp(app) if err == nil { t.Fatal("should fail") } if id != "" { t.Fatal("id should be empty") } if err.Error() != "state isn't expected one of WAITING_RESTORE nor RESTORING but actual: UNKNONWD_STATE" { t.Fatal("fail with unexpected error", err) } } }
func TestOnboardEndnodeAppMapper_gatewayNotReady(t *testing.T) { mapper := newMapper() defer mapper.clear() app := common.App{ AppID: "app67890", AppKey: "app0987654321abcdefghijklmn", ServerLocation: "jp", } mapper.StateTable = &state.Table{ Gateway: state.Onboarding, Apps: map[common.LocalID]state.State{ common.LocalID(app.LocalID()): state.DoneOnboard, }, } id, err := mapper.OnboardEndnodeApp(app) if err == nil { t.Fatal("should fail") } if id != "" { t.Fatal("id should be empty") } if err.Error() != "state is expected one of DONE_ONBOARD but actual: UNKNONWD_STATE" { t.Fatal("fail with unexpected error", err) } }
func (cg *Gateway) mqttDisconnect(app common.App) error { cg.mqttConnectLock.Lock() defer cg.mqttConnectLock.Unlock() localID := app.LocalID() c, ok := cg.mqttClients[localID] if !ok { return fmt.Errorf("MQTT connection not found for: %s", localID) } c.disconnect(false) return nil }
func (cg *Gateway) mqttConnect(app common.App, info common.MQTTInfo) (*mqttConn, error) { cg.mqttConnectLock.Lock() defer cg.mqttConnectLock.Unlock() localID := app.LocalID() _, ok := cg.mqttClients[localID] if ok { return nil, fmt.Errorf("MQTT already connected: %s", app.AppID) } c := &mqttConn{ app: app, Info: info, } if err := c.connect(cg); err != nil { cg.mqttLogConnectError(err) return nil, err } if err := c.subscribe(); err != nil { cg.mqttLogConnectError(err) return nil, err } c.autoReconn = true cg.mqttClients[localID] = c return c, nil }
// DisconnectMQTTClient disconnect mqtt connection with specified app func (cg *Gateway) DisconnectMQTTClient(app common.App) error { cg.mqttConnectLock.Lock() defer cg.mqttConnectLock.Unlock() if c, ok := cg.mqttClients[app.LocalID()]; ok { c.disconnect(true) delete(cg.mqttClients, app.LocalID()) return nil } return errors.New("not mqtt connection for App(" + app.LocalID() + ") not found") }
// OnboardEndnodeApp onboards the Gateway for the Endnode App func (m *Mapper) OnboardEndnodeApp(app common.App) (string, error) { if app.ServerLocation == m.Config.MasterApp.Site && app.AppID == m.Config.MasterApp.AppID { return m.OnboardGatewayApp() } // verify state first if m.StateTable.RestoreMode { return "", state.ErrRestoringGateway } // if gateway state is not DoneOnboard, then resturn err if err := m.StateTable.CheckGatewayState(state.DoneOnboard); err != nil { return "", state.ErrGatewayAppGatewayNotReady } if err := m.StateTable.CheckAppState(common.LocalID(app.LocalID()), state.Onboarding); err == nil { return "", state.ErrOnboarding } // change state of endnode app to onboarding before onboard if err := m.StateTable.ChangeAppState(state.Onboarding, common.LocalID(app.LocalID())); err != nil { return "", err } handleErr := func(err error) (string, error) { m.StateTable.ChangeAppState(state.WaitingOnboard, common.LocalID(app.LocalID())) return "", err } gwID, err := m.onboardGateway(app, true) if err != nil { return handleErr(err) } // change state of endnode app to DoneOnboard after onboard if err := m.StateTable.ChangeAppState(state.DoneOnboard, common.LocalID(app.LocalID())); err != nil { return handleErr(err) } return gwID, nil }
// test OnboardEndnodeApp func TestOnboardEndnodeAppMapper_basic(t *testing.T) { mapper := newMapper() defer mapper.clear() app := common.App{ AppID: "app67890", AppKey: "app0987654321abcdefghijklmn", ServerLocation: "jp", } mapper.StateTable = &state.Table{ Gateway: state.DoneOnboard, Apps: map[common.LocalID]state.State{ common.LocalID(app.LocalID()): state.WaitingOnboard, }, } id, err := mapper.OnboardEndnodeApp(app) if err != nil { t.Fatal("TestOnboardEndnodeAppMapper_basic failed", err) } if id != "th.0001endnode" { t.Error("ThingID should be \"th.0001endnode\":", id) } if mapper.store.appID != "app67890" { t.Error("AppID should be \"app67890\":", mapper.store.appID) } if mapper.cloud.app.AppID != "app67890" { t.Error("AppID should be \"app67890\":", mapper.cloud.app.AppID) } if mapper.cloud.app.AppKey != "app0987654321abcdefghijklmn" { t.Error("AppKey should be \"app0987654321abcdefghijklmn\":", mapper.cloud.app.AppKey) } if mapper.cloud.app.ServerLocation != "jp" { t.Error("ServerLocation should be \"jp\":", mapper.cloud.app.ServerLocation) } if mapper.cloud.called4SaveEndnodeApp != true { t.Error("endnode app should be saved on gateway app") } if mapper.StateTable.Apps[common.LocalID(app.LocalID())] != state.DoneOnboard { t.Fatal("endnode app should be DoneOnboard", mapper.StateTable.Apps[common.LocalID(app.LocalID())]) } }