diff --git a/app/services/events.go b/app/services/events.go index 74b8a23..b655c84 100644 --- a/app/services/events.go +++ b/app/services/events.go @@ -35,8 +35,8 @@ func StartEventHandler() { for range time.NewTicker(time.Minute).C { config.EventChannel <- models.Event{Name: "TimeChanged", Payload: map[string]string{ "weekdayName": time.Now().In(loc).Format("Monday"), - "month": time.Now().In(loc).Format("01"), - "year": time.Now().In(loc).Format("2006"), + "month": time.Now().In(loc).Format("01"), + "year": time.Now().In(loc).Format("2006"), }} } }() @@ -49,7 +49,7 @@ func handleEvent(event models.Event) (responses []models.Event) { startTime := time.Now() defer func() { duration := time.Since(startTime) - if duration > time.Millisecond * 250 { + if duration > time.Millisecond*250 { log.Println(event.Name, "took long to handle:", duration) } }() @@ -134,7 +134,7 @@ func handleEvent(event models.Event) (responses []models.Event) { if action.SetIntensity != nil { newState.Intensity = action.SetIntensity } else if action.AddIntensity != nil { - newIntensity := math.Max(0, math.Min(1, device.State.Intensity + *action.AddIntensity)) + newIntensity := math.Max(0, math.Min(1, device.State.Intensity+*action.AddIntensity)) newState.Intensity = &newIntensity } diff --git a/internal/drivers/hue/bridge.go b/internal/drivers/hue/bridge.go index 48ece0f..cff00ec 100644 --- a/internal/drivers/hue/bridge.go +++ b/internal/drivers/hue/bridge.go @@ -8,20 +8,21 @@ import ( "git.aiterp.net/lucifer/new-server/models" "golang.org/x/sync/errgroup" "io" - "net" + "net" "net/http" "strings" "sync" - "time" + "time" ) type Bridge struct { - mu sync.Mutex - host string - token string - externalID int - lightStates []*hueLightState - sensorStates []*hueSensorState + mu sync.Mutex + host string + token string + externalID int + lightStates []*hueLightState + sensorStates []*hueSensorState + syncingPublish uint32 } func (b *Bridge) Refresh(ctx context.Context) error { @@ -115,10 +116,20 @@ func (b *Bridge) SyncStale(ctx context.Context) error { } for i, input := range inputs { + iCopy := i index := indices[i] inputCopy := input - eg.Go(func() error { return b.putLightState(ctx, index, inputCopy) }) + eg.Go(func() error { + err := b.putLightState(ctx, index, inputCopy) + if err != nil { + return err + } + + b.lightStates[iCopy].stale = false + + return nil + }) } return eg.Wait() diff --git a/internal/drivers/hue/driver.go b/internal/drivers/hue/driver.go index fc327b5..7044d93 100644 --- a/internal/drivers/hue/driver.go +++ b/internal/drivers/hue/driver.go @@ -10,6 +10,7 @@ import ( "net/http" "strconv" "sync" + "sync/atomic" "time" ) @@ -309,6 +310,9 @@ func (d *Driver) Publish(ctx context.Context, bridge models.Bridge, devices []mo } b.mu.Unlock() + atomic.StoreUint32(&b.syncingPublish, 1) + defer atomic.StoreUint32(&b.syncingPublish, 0) + return b.SyncStale(ctx) } @@ -327,6 +331,10 @@ func (d *Driver) Run(ctx context.Context, bridge models.Bridge, ch chan<- models for { select { case <-selectedTicker.C: + if atomic.LoadUint32(&b.syncingPublish) == 1 { + continue + } + if ticksUntilRefresh <= 0 { err := b.Refresh(ctx) if err != nil { diff --git a/internal/mysql/devicerepo.go b/internal/mysql/devicerepo.go index 4ff1ba7..25d8df9 100644 --- a/internal/mysql/devicerepo.go +++ b/internal/mysql/devicerepo.go @@ -56,22 +56,28 @@ func (r *DeviceRepo) Find(ctx context.Context, id int) (*models.Device, error) { } func (r *DeviceRepo) FetchByReference(ctx context.Context, kind models.ReferenceKind, value string) ([]models.Device, error) { - var err error - records := make([]deviceRecord, 0, 8) + q := sq.Select("device.*").From("device") switch kind { case models.RKDeviceID: - err = r.DBX.SelectContext(ctx, &records, "SELECT * FROM device WHERE id=?", value) + q = q.Where(sq.Eq{"id": strings.Split(value, ",")}) case models.RKBridgeID: - err = r.DBX.SelectContext(ctx, &records, "SELECT * FROM device WHERE bridge_id=?", value) + q = q.Where(sq.Eq{"bridge_id": strings.Split(value, ",")}) case models.RKTag: - err = r.DBX.SelectContext(ctx, &records, "SELECT device.* FROM device JOIN device_tag dt ON device.id = dt.device_id WHERE dt.tag_name=?", value) + q = q.Join("device_tag dt ON device.id=dt.device_id").Where(sq.Eq{"dt.tag_name": strings.Split(value, ",")}) case models.RKAll: - err = r.DBX.SelectContext(ctx, &records, "SELECT device.* FROM device") default: log.Println("Unknown reference kind used for device fetch:", kind) return []models.Device{}, nil } + + query, args, err := q.ToSql() + if err != nil { + return nil, dbErr(err) + } + + records := make([]deviceRecord, 0, 8) + err = r.DBX.SelectContext(ctx, &records, query, args...) if err != nil { return nil, dbErr(err) }