From 7fa3d252c9904e95833da4323deeb4aec9b8df8c Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 3 Jan 2024 22:54:39 +0100 Subject: [PATCH] chore: remove dead code (#11451) --- cmd/configure/types.go | 4 - cmd/detect/analyze.go | 84 ------------ core/planner/planner.go | 7 - server/db/settings/store.go | 21 --- server/http.go | 16 --- util/jq/jq.go | 47 ------- util/locale/locale.go | 14 -- util/modbus/functions.go | 6 - util/pipe/limiter.go | 38 ------ util/pipe/limiter_test.go | 43 ------ util/request/functions.go | 5 - vehicle/bluelink/params.go | 6 + vehicle/bluelink/stamps.go | 81 ----------- vehicle/ford/api.go | 49 ------- vehicle/ford/types.go | 62 --------- vehicle/volvo/connected/identity.go1 | 177 ------------------------- vehicle/volvo/connected/tokensource.go | 34 ----- vehicle/vw/api.go | 11 -- 18 files changed, 6 insertions(+), 699 deletions(-) delete mode 100644 server/db/settings/store.go create mode 100644 vehicle/bluelink/params.go delete mode 100644 vehicle/bluelink/stamps.go delete mode 100644 vehicle/volvo/connected/identity.go1 delete mode 100644 vehicle/volvo/connected/tokensource.go diff --git a/cmd/configure/types.go b/cmd/configure/types.go index ac2d22e52..c8c6fd61a 100644 --- a/cmd/configure/types.go +++ b/cmd/configure/types.go @@ -10,10 +10,6 @@ const ( type UsageChoice string -func (u UsageChoice) String() string { - return string(u) -} - type DeviceCategory string func (c DeviceCategory) String() string { diff --git a/cmd/detect/analyze.go b/cmd/detect/analyze.go index 5c9e7ff62..2c4ff63e9 100644 --- a/cmd/detect/analyze.go +++ b/cmd/detect/analyze.go @@ -4,27 +4,6 @@ import "github.com/evcc-io/evcc/cmd/detect/tasks" type Criteria map[string]interface{} -func filter(list []tasks.Result, criteria []Criteria) (match []tasks.Result) { - for _, res := range list { - for _, criterium := range criteria { - ok := true - - for matchKey, matchVal := range criterium { - if foundVal, found := res.Attributes[matchKey]; !found || foundVal != matchVal { - ok = false - break - } - } - - if ok { - match = append(match, res) - } - } - } - - return match -} - type TypeSummary struct { Results []tasks.Result Found, Unique bool @@ -33,66 +12,3 @@ type TypeSummary struct { type Summary struct { Charger, Grid, PV, Charge, Battery, Meter TypeSummary } - -func summarize(res []tasks.Result) TypeSummary { - return TypeSummary{ - Results: res, - Found: len(res) > 0, - Unique: len(res) == 1, - } -} - -const ( - tid = "task.id" - smaHttp = "details.http" -) - -func Consolidate(res []tasks.Result) Summary { - grid := filter(res, []Criteria{ - {tid: taskOpenwb}, - {tid: taskSMA, smaHttp: false}, - {tid: taskE3DC}, - {tid: taskSonnen}, - }) - - pv := filter(res, []Criteria{ - {tid: taskOpenwb}, - {tid: taskInverter}, - }) - - battery := filter(res, []Criteria{ - {tid: taskOpenwb}, - {tid: taskE3DC}, - {tid: taskSonnen}, - {tid: taskBattery}, - }) - - charger := filter(res, []Criteria{ - {tid: taskOpenwb}, - {tid: taskWallbe}, - {tid: taskPhoenixEMEth}, - {tid: taskPhoenixEVEth}, - {tid: taskEVSEWifi}, - {tid: taskGoE}, - {tid: taskKEBA}, - }) - - charge := filter(res, []Criteria{ - {tid: taskOpenwb}, - {tid: taskKEBA}, - }) - - meter := filter(res, []Criteria{ - {tid: taskSMA, smaHttp: true}, - {tid: taskMeter}, - }) - - return Summary{ - Grid: summarize(grid), - PV: summarize(pv), - Battery: summarize(battery), - Charger: summarize(charger), - Charge: summarize(charge), - Meter: summarize(meter), - } -} diff --git a/core/planner/planner.go b/core/planner/planner.go index feb57845e..74929a4a5 100644 --- a/core/planner/planner.go +++ b/core/planner/planner.go @@ -16,13 +16,6 @@ type Planner struct { tariff api.Tariff } -// WithClock sets a mockable clock -func WithClock(clock clock.Clock) func(t *Planner) { - return func(t *Planner) { - t.clock = clock - } -} - // New creates a price planner func New(log *util.Logger, tariff api.Tariff, opt ...func(t *Planner)) *Planner { p := &Planner{ diff --git a/server/db/settings/store.go b/server/db/settings/store.go deleted file mode 100644 index 4c0dea769..000000000 --- a/server/db/settings/store.go +++ /dev/null @@ -1,21 +0,0 @@ -package settings - -import "github.com/evcc-io/evcc/api/store" - -type storer struct { - key string -} - -var _ store.Store = (*storer)(nil) - -func NewStore(key string) store.Store { - return &storer{key: key} -} - -func (s *storer) Load(res any) error { - return Json(s.key, &res) -} - -func (s *storer) Save(val any) error { - return SetJson(s.key, val) -} diff --git a/server/http.go b/server/http.go index cade80bfe..ccb796cb3 100644 --- a/server/http.go +++ b/server/http.go @@ -20,22 +20,6 @@ type route struct { HandlerFunc http.HandlerFunc } -// routeLogger traces matched routes including their executing time -// -//lint:ignore U1000 if needed -func routeLogger(inner http.Handler) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - start := time.Now() - inner.ServeHTTP(w, r) - log.TRACE.Printf( - "%s\t%s\t%s", - r.Method, - r.RequestURI, - time.Since(start), - ) - } -} - // HTTPd wraps an http.Server and adds the root router type HTTPd struct { *http.Server diff --git a/util/jq/jq.go b/util/jq/jq.go index c8a1fd61d..2cd6694bb 100644 --- a/util/jq/jq.go +++ b/util/jq/jq.go @@ -32,50 +32,3 @@ func Query(query *gojq.Query, input []byte) (interface{}, error) { return v, nil } - -// Float64 converts interface to float64 -func Float64(v interface{}) (float64, error) { - switch v := v.(type) { - case int: - return float64(v), nil - case float64: - return v, nil - default: - return 0, fmt.Errorf("unexpected float type: %T", v) - } -} - -// Int64 converts interface to int64 -func Int64(v interface{}) (int64, error) { - switch v := v.(type) { - case int: - return int64(v), nil - case float64: - if float64(int64(v)) == v { - return int64(v), nil - } - return 0, fmt.Errorf("unexpected int64: %v", v) - default: - return 0, fmt.Errorf("unexpected int64 type: %T", v) - } -} - -// String converts interface to string -func String(v interface{}) (string, error) { - switch v := v.(type) { - case string: - return v, nil - default: - return "", fmt.Errorf("unexpected string type: %T", v) - } -} - -// Bool converts interface to bool -func Bool(v interface{}) (bool, error) { - switch v := v.(type) { - case bool: - return v, nil - default: - return false, fmt.Errorf("unexpected bool type: %T", v) - } -} diff --git a/util/locale/locale.go b/util/locale/locale.go index 3d19c2021..884512071 100644 --- a/util/locale/locale.go +++ b/util/locale/locale.go @@ -46,17 +46,3 @@ func Init() error { return nil } - -func Localize(lc *Config) string { - msg, _, err := Localizer.LocalizeWithTag(lc) - if err != nil { - msg = lc.MessageID - } - return msg -} - -func LocalizeID(id string) string { - return Localize(&Config{ - MessageID: id, - }) -} diff --git a/util/modbus/functions.go b/util/modbus/functions.go index 8c6797e13..a6fc0f5c0 100644 --- a/util/modbus/functions.go +++ b/util/modbus/functions.go @@ -4,16 +4,10 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "math" "strconv" "strings" ) -func RTUFloat64ToFloat64(b []byte) float64 { - bits := binary.BigEndian.Uint64(b) - return math.Float64frombits(bits) -} - // decodeMask converts a bit mask in decimal or hex format to uint64 func decodeMask(mask string) (uint64, error) { mask = strings.ToLower(mask) diff --git a/util/pipe/limiter.go b/util/pipe/limiter.go index c45ccd09c..726f04fff 100644 --- a/util/pipe/limiter.go +++ b/util/pipe/limiter.go @@ -64,44 +64,6 @@ func (l *Deduplicator) Pipe(in <-chan util.Param) <-chan util.Param { return out } -// Limiter allows filtering of channel data by given criteria -type Limiter struct { - clock clock.Clock - interval time.Duration - cache map[string]cacheItem -} - -// NewLimiter creates limiter -func NewLimiter(interval time.Duration) Piper { - l := &Limiter{ - clock: clock.New(), - interval: interval, - cache: make(map[string]cacheItem), - } - - return l -} - -func (l *Limiter) pipe(in <-chan util.Param, out chan<- util.Param) { - for p := range in { - key := p.UniqueID() - item, cached := l.cache[key] - - // forward if not cached or expired - if !cached || l.clock.Since(item.updated) >= l.interval { - l.cache[key] = cacheItem{updated: l.clock.Now(), val: p.Val} - out <- p - } - } -} - -// Pipe creates a new filtered output channel for given input channel -func (l *Limiter) Pipe(in <-chan util.Param) <-chan util.Param { - out := make(chan util.Param) - go l.pipe(in, out) - return out -} - // Dropper allows filtering of channel data by given criteria type Dropper struct { filter []string diff --git a/util/pipe/limiter_test.go b/util/pipe/limiter_test.go index bdba6b03e..870d3fd63 100644 --- a/util/pipe/limiter_test.go +++ b/util/pipe/limiter_test.go @@ -9,49 +9,6 @@ import ( "github.com/evcc-io/evcc/util" ) -func TestLimiter(t *testing.T) { - l := NewLimiter(time.Hour).(*Limiter) - clck := clock.NewMock() - l.clock = clck - - in := make(chan util.Param) - out := l.Pipe(in) - - p := util.Param{Key: "k", Val: 1} - in <- p - - if o := <-out; o.Key != p.Key || o.Val != p.Val { - t.Errorf("unexpected param %v", o) - } - - p.Val = 2 - in <- p - - runtime.Gosched() - select { - case o := <-out: - t.Errorf("unexpected param %v", o) - case <-time.After(time.Millisecond): - } - - clck.Add(2 * l.interval) - p.Val = 3 - in <- p - - if o := <-out; o.Key != p.Key || o.Val != p.Val { - t.Errorf("unexpected param %v", o) - } - - // allow nils - clck.Add(2 * l.interval) - p.Val = nil - in <- p - - if o := <-out; o.Key != p.Key || o.Val != p.Val { - t.Errorf("unexpected param %v", o) - } -} - func TestDeduplicator(t *testing.T) { l := NewDeduplicator(time.Hour, "filtered").(*Deduplicator) clck := clock.NewMock() diff --git a/util/request/functions.go b/util/request/functions.go index f18a2d8a3..411d47f2d 100644 --- a/util/request/functions.go +++ b/util/request/functions.go @@ -43,11 +43,6 @@ type StatusError struct { resp *http.Response } -// NewStatusError create new StatusError for given response -func NewStatusError(resp *http.Response) StatusError { - return StatusError{resp: resp} -} - func (e StatusError) Error() string { return fmt.Sprintf("unexpected status: %d (%s)", e.resp.StatusCode, http.StatusText(e.resp.StatusCode)) } diff --git a/vehicle/bluelink/params.go b/vehicle/bluelink/params.go new file mode 100644 index 000000000..6f850bb44 --- /dev/null +++ b/vehicle/bluelink/params.go @@ -0,0 +1,6 @@ +package bluelink + +const ( + KiaAppID = "a2b8469b-30a3-4361-8e13-6fceea8fbe74" + HyundaiAppID = "014d2225-8495-4735-812d-2616334fd15d" +) diff --git a/vehicle/bluelink/stamps.go b/vehicle/bluelink/stamps.go deleted file mode 100644 index 2ea6b96eb..000000000 --- a/vehicle/bluelink/stamps.go +++ /dev/null @@ -1,81 +0,0 @@ -package bluelink - -import ( - "errors" - "fmt" - "sync" - "time" - - "github.com/evcc-io/evcc/util" - "github.com/evcc-io/evcc/util/request" -) - -const ( - KiaAppID = "a2b8469b-30a3-4361-8e13-6fceea8fbe74" - HyundaiAppID = "014d2225-8495-4735-812d-2616334fd15d" -) - -type stampCollection struct { - mu sync.Mutex - log *util.Logger - AppID, Brand string - Stamps []string - Generated time.Time - Frequency int - updated time.Time -} - -var ( - client = request.NewHelper(util.NewLogger("http")) - - Stamps = map[string]*stampCollection{ - KiaAppID: {log: util.NewLogger("kia"), AppID: KiaAppID, Brand: "kia"}, - HyundaiAppID: {log: util.NewLogger("hyundai"), AppID: HyundaiAppID, Brand: "hyundai"}, - } -) - -// New creates a new stamp -func (c *stampCollection) Get() (string, error) { - c.mu.Lock() - defer c.mu.Unlock() - - var position int - if c.Frequency > 0 { - position = int(time.Since(c.Generated).Milliseconds()) / c.Frequency - } - - // download - if position >= len(c.Stamps)*9/10 { - 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 - } - } - - position = int(time.Since(c.Generated).Milliseconds()) / c.Frequency - } - - if len(c.Stamps) == 0 { - return "", errors.New("no stamps available") - } - - if position >= len(c.Stamps) { - position = len(c.Stamps) - 1 - } - - return c.Stamps[position], nil -} - -// updateStamps updates stamps according to https://github.com/Hacksore/bluelinky/pull/144 -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) - } - - return nil -} diff --git a/vehicle/ford/api.go b/vehicle/ford/api.go index 374765459..606a7ca6f 100644 --- a/vehicle/ford/api.go +++ b/vehicle/ford/api.go @@ -1,7 +1,6 @@ package ford import ( - "errors" "fmt" "net/http" @@ -72,51 +71,3 @@ func (v *API) Vehicles() ([]string, error) { return res, err } - -// Status performs a /status request -func (v *API) Status(vin string) (StatusResponse, error) { - uri := fmt.Sprintf("%s/api/vehicles/v5/%s/status", ApiURI, vin) - - var res StatusResponse - err := v.GetJSON(uri, &res) - - return res, err -} - -// RefreshResult retrieves a refresh result using /statusrefresh -func (v *API) RefreshResult(vin, refreshId string) (StatusResponse, error) { - var res StatusResponse - - uri := fmt.Sprintf("%s/api/vehicles/v5/%s/statusrefresh/%s", ApiURI, vin, refreshId) - err := v.GetJSON(uri, &res) - - return res, err -} - -// RefreshRequest requests status refresh tracked by commandId -func (v *API) RefreshRequest(vin string) (string, error) { - var resp struct { - CommandId string - } - - uri := fmt.Sprintf("%s/api/vehicles/v5/%s/status", ApiURI, vin) - req, err := http.NewRequest(http.MethodPut, uri, nil) - if err == nil { - err = v.DoJSON(req, &resp) - } - - if err == nil && resp.CommandId == "" { - err = errors.New("refresh failed") - } - - return resp.CommandId, err -} - -// WakeUp performs a wakeup request -func (v *API) WakeUp(vin string) error { - uri := fmt.Sprintf("%s/api/dashboard/v1/users/vehicles?wakeupVin=%s", TokenURI, vin) - - _, err := v.GetBody(uri) - - return err -} diff --git a/vehicle/ford/types.go b/vehicle/ford/types.go index a1c28780d..3d4f80abb 100644 --- a/vehicle/ford/types.go +++ b/vehicle/ford/types.go @@ -1,10 +1,5 @@ package ford -import ( - "strings" - "time" -) - type VehiclesResponse struct { UserVehicles struct { VehicleDetails []struct { @@ -12,60 +7,3 @@ type VehiclesResponse struct { } } } - -// StatusResponse is the response to the vehicle status request -type StatusResponse struct { - VehicleStatus struct { - BatteryFillLevel struct { - Value float64 - Timestamp Timestamp - } - ElVehDTE struct { - Value float64 - Timestamp Timestamp - } - ChargingStatus struct { - Value string - Timestamp Timestamp - } - ChargeEndTime struct { - Value Timestamp - Timestamp Timestamp - } - PlugStatus struct { - Value int - Timestamp Timestamp - } - Odometer struct { - Value float64 - Timestamp Timestamp - } - Gps struct { - Latitude float64 `json:",string"` - Longitude float64 `json:",string"` - GpsState string - Timestamp Timestamp - } - LastRefresh Timestamp - } - Status int -} - -const TimeFormat = "01-02-2006 15:04:05" // time format used by Ford API, time is in UTC - -// Timestamp implements JSON unmarshal -type Timestamp struct { - time.Time -} - -// UnmarshalJSON decodes string timestamp into time.Time -func (ct *Timestamp) UnmarshalJSON(data []byte) error { - s := strings.Trim(string(data), "\"") - - t, err := time.Parse(TimeFormat, s) - if err == nil { - ct.Time = t - } - - return err -} diff --git a/vehicle/volvo/connected/identity.go1 b/vehicle/volvo/connected/identity.go1 deleted file mode 100644 index 3aa7224c0..000000000 --- a/vehicle/volvo/connected/identity.go1 +++ /dev/null @@ -1,177 +0,0 @@ -package connected - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/url" - "os" - "strings" - - "github.com/coreos/go-oidc/v3/oidc" - "github.com/evcc-io/evcc/provider" - "github.com/evcc-io/evcc/server/auth" - "github.com/evcc-io/evcc/util" - "github.com/evcc-io/evcc/util/request" - "golang.org/x/oauth2" -) - -type IdentityOptions func(c *Identity) error - -// // WithToken provides an oauth2.Token to the client for auth. -// func WithToken(t *oauth2.Token) IdentityOptions { -// return func(v *Identity) error { -// v.ReuseTokenSource.Apply(t) -// return nil -// } -// } - -type Identity struct { - log *util.Logger - *request.Helper - *ReuseTokenSource - oc *oauth2.Config - baseURL string - authC chan<- bool -} - -// TODO SessionSecret from config/persistence -func NewIdentity(log *util.Logger, id, secret string, options ...IdentityOptions) (*Identity, error) { - // provider, err := oidc.NewProvider(context.Background(), "https://id.mercedes-benz.com") - // if err != nil { - // return nil, fmt.Errorf("failed to initialize OIDC provider: %s", err) - // } - - oc := &oauth2.Config{ - ClientID: id, - ClientSecret: secret, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://volvoid.eu.volvocars.com/as/authorization.oauth2", - TokenURL: "https://volvoid.eu.volvocars.com/as/token.oauth2", - }, - Scopes: []string{oidc.ScopeOpenID, "conve:fuel_status", "conve:odometer_status", "conve:environment"}, - } - - v := &Identity{ - log: log, - Helper: request.NewHelper(log), - oc: oc, - } - - ts := &ReuseTokenSource{ - oc: oc, - cb: v.invalidToken, - } - ts.Apply(nil) - - v.ReuseTokenSource = ts - - // for _, o := range options { - // if err == nil { - // err = o(v) - // } - // } - - return v, nil -} - -func (v *Identity) Login(user, password string) error { - oc := v.ReuseTokenSource.oc - data := url.Values{ - "username": {user}, - "password": {password}, - "access_token_manager_id": {"JWTh4Yf0b"}, - "grant_type": {"password"}, - "scope": oc.Scopes, - } - - req, err := request.New(http.MethodPost, oc.Endpoint.AuthURL, strings.NewReader(data.Encode()), map[string]string{ - "Content-Type": request.FormContent, - "Authorization": "Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=", - }) - if err != nil { - return err - } - - var res string - err = v.DoJSON(req, &res) - - os.Exit(1) - - return err -} - -// invalidToken is the callback for the token source when token expires -func (v *Identity) invalidToken() { - if v.authC != nil { - v.authC <- false - } -} - -// var _ api.ProviderLogin = (*Identity)(nil) - -func (v *Identity) SetCallbackParams(baseURL, redirectURL string, authC chan<- bool) { - v.baseURL = baseURL - v.oc.RedirectURL = redirectURL - v.authC = authC -} - -func (v *Identity) LoginHandler() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - state := auth.Register(v.callbackHandler) - - fmt.Println(v.oc.AuthCodeURL(state)) - - b, _ := json.Marshal(struct { - LoginUri string `json:"loginUri"` - }{ - LoginUri: v.oc.AuthCodeURL(state), //, oauth2.AccessTypeOffline), // oauth2.SetAuthURLParam("prompt", "login consent"), - }) - - w.WriteHeader(http.StatusOK) - _, _ = w.Write(b) - } -} - -func (v *Identity) LogoutHandler() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - v.ReuseTokenSource.Apply(nil) - v.authC <- false - - w.WriteHeader(http.StatusOK) - _, _ = w.Write(nil) - } -} - -func (v *Identity) callbackHandler(w http.ResponseWriter, r *http.Request) { - v.log.TRACE.Println("callback request retrieved") - - data, err := url.ParseQuery(r.URL.RawQuery) - if err != nil { - fmt.Fprintln(w, "invalid response:", data) - return - } - - codes, ok := data["code"] - if !ok || len(codes) != 1 { - fmt.Fprintln(w, "invalid response:", data) - return - } - - token, err := v.oc.Exchange(context.Background(), codes[0]) - if err != nil { - fmt.Fprintln(w, "token error:", err) - return - } - - if token.Valid() { - v.log.TRACE.Println("sending login update...") - v.ReuseTokenSource.Apply(token) - v.authC <- true - - provider.ResetCached() - } - - http.Redirect(w, r, v.baseURL, http.StatusFound) -} diff --git a/vehicle/volvo/connected/tokensource.go b/vehicle/volvo/connected/tokensource.go deleted file mode 100644 index 1c8c602b5..000000000 --- a/vehicle/volvo/connected/tokensource.go +++ /dev/null @@ -1,34 +0,0 @@ -package connected - -import ( - "context" - "sync" - - "golang.org/x/oauth2" -) - -type ReuseTokenSource struct { - mu sync.Mutex - oc *oauth2.Config - ts oauth2.TokenSource - cb func() -} - -func (ts *ReuseTokenSource) Token() (*oauth2.Token, error) { - ts.mu.Lock() - defer ts.mu.Unlock() - - t, err := ts.ts.Token() - if err != nil || !t.Valid() { - // invalid token callback - ts.cb() - } - - return t, err -} - -func (ts *ReuseTokenSource) Apply(t *oauth2.Token) { - ts.mu.Lock() - ts.ts = ts.oc.TokenSource(context.Background(), t) - ts.mu.Unlock() -} diff --git a/vehicle/vw/api.go b/vehicle/vw/api.go index 734cef5e7..86b5c4c08 100644 --- a/vehicle/vw/api.go +++ b/vehicle/vw/api.go @@ -41,17 +41,6 @@ func NewAPI(log *util.Logger, ts oauth2.TokenSource, brand, country string) *API return v } -// Vehicles implements the /vehicles response -func (v *API) Vehicles() ([]string, error) { - var res VehiclesResponse - uri := fmt.Sprintf("%s/usermanagement/users/v1/%s/%s/vehicles", v.baseURI, v.brand, v.country) - err := v.GetJSON(uri, &res) - if err != nil && res.Error != nil { - err = res.Error.Error() - } - return res.UserVehicles.Vehicle, err -} - // HomeRegion updates the home region for the given vehicle func (v *API) HomeRegion(vin string) error { var res HomeRegion