Bluelink: fix handling of stamps (#2936)

This commit is contained in:
andig 2022-03-19 12:00:28 +01:00 • committed by GitHub
parent 37f4a5679f
commit 6787bd464e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 64 deletions

View file

@ -55,19 +55,15 @@ func NewIdentity(log *util.Logger, config Config) *Identity {
config: config,
}
// fetch updated stamps
updateStamps(log, config.CCSPApplicationID)
return v
}
// Credits to https://openwb.de/forum/viewtopic.php?f=5&t=1215&start=10#p11877
func (v *Identity) stamp() string {
return Stamps.New(v.config.CCSPApplicationID)
}
func (v *Identity) getDeviceID() (string, error) {
stamp, err := Stamps[v.config.CCSPApplicationID].Get()
if err != nil {
return "", err
}
uniID, _ := uuid.NewUUID()
data := map[string]interface{}{
"pushRegId": "1",
@ -79,7 +75,7 @@ func (v *Identity) getDeviceID() (string, error) {
"ccsp-service-id": v.config.CCSPServiceID,
"Content-type": "application/json;charset=UTF-8",
"User-Agent": "okhttp/3.10.0",
"Stamp": v.stamp(),
"Stamp": stamp,
}
var resp struct {
@ -362,6 +358,11 @@ func (v *Identity) Login(user, password, language string) (err error) {
// Request decorates requests with authorization headers
func (v *Identity) Request(req *http.Request) error {
stamp, err := Stamps[v.config.CCSPApplicationID].Get()
if err != nil {
return err
}
token, err := v.Token()
if err != nil {
return err
@ -373,7 +374,7 @@ func (v *Identity) Request(req *http.Request) error {
"ccsp-application-id": v.config.CCSPApplicationID,
"offset": "1",
"User-Agent": "okhttp/3.10.0",
"Stamp": v.stamp(),
"Stamp": stamp,
} {
req.Header.Set(k, v)
}

View file

@ -15,72 +15,62 @@ const (
HyundaiAppID = "014d2225-8495-4735-812d-2616334fd15d"
)
// StampsRegistry collects stamps for a single brand
type StampsRegistry map[string]*StampCollection
type StampCollection struct {
Stamps []string
Generated time.Time
Frequency float64
}
var Stamps = StampsRegistry{
KiaAppID: nil,
HyundaiAppID: nil,
type stampCollection struct {
mu sync.Mutex
log *util.Logger
AppID, Brand string
Stamps []string
Generated time.Time
Frequency float64
updated time.Time
}
var (
mu sync.Mutex
updater map[string]struct{} = make(map[string]struct{})
client = request.NewHelper(util.NewLogger("http"))
brands = map[string]string{
KiaAppID: "kia",
HyundaiAppID: "hyundai",
Stamps = map[string]*stampCollection{
KiaAppID: {log: util.NewLogger("kia"), AppID: KiaAppID, Brand: "kia"},
HyundaiAppID: {log: util.NewLogger("hyundai"), AppID: HyundaiAppID, Brand: "hyundai"},
}
)
func download(log *util.Logger, id, brand string) {
var res StampCollection
uri := fmt.Sprintf("https://raw.githubusercontent.com/neoPix/bluelinky-stamps/master/%s-%s.v2.json", brand, id)
// New creates a new stamp
func (c *stampCollection) Get() (string, error) {
c.mu.Lock()
defer c.mu.Unlock()
if err := client.GetJSON(uri, &res); err != nil {
log.ERROR.Println(err)
return
length := float64(len(c.Stamps))
position := float64(time.Since(c.Generated).Milliseconds()) / c.Frequency
// download
if position >= 0.9*length {
if time.Since(c.updated) > 15*time.Minute {
c.log.TRACE.Printf("retry stamps download, last attempt: %v", c.updated)
if err := c.download(); err != nil {
return "", err
}
}
length = float64(len(c.Stamps))
position = float64(time.Since(c.Generated).Milliseconds()) / c.Frequency
}
mu.Lock()
Stamps[id] = &res
mu.Unlock()
if position >= length {
position = length - 1
}
return c.Stamps[int64(position+5*rand.Float64())], nil
}
// updateStamps updates stamps according to https://github.com/Hacksore/bluelinky/pull/144
func updateStamps(log *util.Logger, id string) {
if _, ok := updater[id]; ok {
return
func (c *stampCollection) download() error {
c.updated = time.Now()
uri := fmt.Sprintf("https://raw.githubusercontent.com/neoPix/bluelinky-stamps/master/%s-%s.v2.json", c.Brand, c.AppID)
if err := client.GetJSON(uri, &c); err != nil {
return fmt.Errorf("failed to download stamps: %w", err)
}
updater[id] = struct{}{}
download(log, id, brands[id])
go func() {
for range time.NewTicker(24 * time.Hour).C {
download(log, id, brands[id])
}
}()
}
// New creates a new stamp
func (s StampsRegistry) New(id string) string {
mu.Lock()
defer mu.Unlock()
source := s[id]
if source == nil {
panic(id)
}
position := float64(time.Since(source.Generated).Milliseconds()) / source.Frequency
return source.Stamps[int64(position+5*rand.Float64())]
return nil
}