208 lines
7.0 KiB
Go
208 lines
7.0 KiB
Go
package immobilizershared
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"fiskerinc.com/modules/logger"
|
|
"fiskerinc.com/modules/redisv2"
|
|
)
|
|
|
|
// Grabs all the vehicle statuses from redis
|
|
func ReadVehicleStatuses(connection *redisv2.Connection) (results map[string]ImmobilizeTrack, err error) {
|
|
res := connection.HGetAll(context.Background(), IMMOBILIZER_HASHSET_NAME)
|
|
tempMap, err := res.Result()
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "ReadVehicleStatuses").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
|
|
results = make(map[string]ImmobilizeTrack)
|
|
for key, value := range tempMap {
|
|
tempTrack := ImmobilizeTrack{}
|
|
err = json.Unmarshal([]byte(value), &tempTrack)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "ReadVehicleStatuses").Msg("Immobilizer Error")
|
|
continue
|
|
}
|
|
results[key] = tempTrack
|
|
}
|
|
return
|
|
}
|
|
|
|
// WE want to update redis with the fact a car is immobilized, so start with modifying redis, then sending a publish event
|
|
// This kind of specification per function is sort of silly, probably will want to change in the future
|
|
func UpdateCarImmobilized(vin string, connection *redisv2.Connection) (err error) {
|
|
err = SetVehicleImmobilized(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarImmobilized").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
err = PublishVehicleImmobilized(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarImmobilized").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func UpdateCarImmobilizing(vin string, connection *redisv2.Connection) (err error) {
|
|
err = SetVehicleImmobilizing(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarImmobilizing").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
err = PublishVehicleImmobilizing(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarImmobilizing").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func UpdateCarMobilized(vin string, connection *redisv2.Connection) (err error) {
|
|
err = SetVehicleMobilized(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarMobilized").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
err = PublishVehicleMobilized(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarMobilized").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func UpdateCarMobilizing(vin string, connection *redisv2.Connection) (err error) {
|
|
err = SetVehicleMobilizing(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarMobilizing").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
err = PublishVehicleMobilizing(vin, connection)
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "UpdateCarMobilizing").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// Might not need to call these directly
|
|
// Publishing the fact the car is now mobilized. Ditto's will remove the car from their containers
|
|
func PublishVehicleMobilized(vin string, connection *redisv2.Connection) (err error) {
|
|
return PublishVehicleMobilizationChange(RedisImmobilizerMsg{VIN: vin, State: STATE_MOBILIZED}, connection)
|
|
}
|
|
|
|
func PublishVehicleMobilizing(vin string, connection *redisv2.Connection) (err error) {
|
|
return PublishVehicleMobilizationChange(RedisImmobilizerMsg{VIN: vin, State: STATE_MOBILIZING}, connection)
|
|
}
|
|
|
|
func PublishVehicleImmobilized(vin string, connection *redisv2.Connection) (err error) {
|
|
return PublishVehicleMobilizationChange(RedisImmobilizerMsg{VIN: vin, State: STATE_IMMOBILIZED}, connection)
|
|
}
|
|
|
|
// Publish the fact we are trying to immobile the vehicle
|
|
func PublishVehicleImmobilizing(vin string, connection *redisv2.Connection) (err error) {
|
|
return PublishVehicleMobilizationChange(RedisImmobilizerMsg{VIN: vin, State: STATE_IMMOBILIZING}, connection)
|
|
}
|
|
|
|
func PublishVehicleMobilizationChange(msg RedisImmobilizerMsg, connection *redisv2.Connection) (err error) {
|
|
// I think the int that is returned is the number of subscribers
|
|
res := connection.Publish(context.Background(), IMMOBILIZER_PUBSUB_CHANNEL, msg)
|
|
err = res.Err()
|
|
return
|
|
}
|
|
|
|
// These all modify the redis data store, which acts as a database for the cars that are immobilized
|
|
func SetVehicleMobilized(vin string, connection *redisv2.Connection) (err error) {
|
|
// Instead of using HSET, we are deleting the car from the immobilized stats line. Keeps the redis store smaller
|
|
res := connection.HDel(context.Background(), IMMOBILIZER_HASHSET_NAME, vin)
|
|
err = res.Err()
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "SetVehicleMobilized").Msg("Immobilizer Error")
|
|
}
|
|
return
|
|
}
|
|
|
|
func SetVehicleMobilizing(vin string, connection *redisv2.Connection) (err error) {
|
|
return setVehicleMobilizationChange(vin, ImmobilizeTrack{State: STATE_MOBILIZING}, connection)
|
|
}
|
|
|
|
func SetVehicleImmobilized(vin string, connection *redisv2.Connection) (err error) {
|
|
return setVehicleMobilizationChange(vin, ImmobilizeTrack{State: STATE_IMMOBILIZED}, connection)
|
|
}
|
|
|
|
// Set the fact we are trying to immobile the vehicle
|
|
func SetVehicleImmobilizing(vin string, connection *redisv2.Connection) (err error) {
|
|
return setVehicleMobilizationChange(vin, ImmobilizeTrack{State: STATE_IMMOBILIZING}, connection)
|
|
}
|
|
|
|
// CHANGE
|
|
func setVehicleMobilizationChange(vin string, msg ImmobilizeTrack, connection *redisv2.Connection) (err error) {
|
|
// I think the int that is returned is the number of subscribers
|
|
res := connection.HSet(context.Background(), IMMOBILIZER_HASHSET_NAME, vin, msg)
|
|
err = res.Err()
|
|
if err != nil {
|
|
logger.Err(err).Stack().Str("function", "setVehicleMobilizationChange").Msg("Immobilizer Error")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
const IMMOBILIZER_PUBSUB_CHANNEL = "immobilizer"
|
|
const IMMOBILIZER_HASHSET_NAME = "immobilizer"
|
|
|
|
type ImmobilizeTrack struct {
|
|
State ImmobilizeState
|
|
// IDK, do we need the time we tried? We probably need a timer thing
|
|
CreatedAt *time.Time
|
|
UpdatedAt *time.Time
|
|
}
|
|
|
|
// For redis serialization
|
|
func (it ImmobilizeTrack) MarshalBinary() ([]byte, error) {
|
|
return json.Marshal(it)
|
|
}
|
|
|
|
func (it ImmobilizeTrack) UnmarshalBinary(data []byte) error {
|
|
return json.Unmarshal(data, &it)
|
|
}
|
|
|
|
type ImmobilizeState int
|
|
|
|
var (
|
|
STATE_IMMOBILIZED ImmobilizeState = 0 // Car officially immobilized
|
|
STATE_IMMOBILIZING ImmobilizeState = 1 // Trying to immobilize car
|
|
STATE_MOBILIZING ImmobilizeState = 2 // Trying to mobilize the car
|
|
STATE_MOBILIZED ImmobilizeState = 3 // Car is mobilized, although not stored in redis or ditto, is used to communicate the change has been made
|
|
)
|
|
|
|
func (i ImmobilizeState) String()(string){
|
|
switch i{
|
|
case STATE_IMMOBILIZED:
|
|
return "STATE_IMMOBILIZED"
|
|
case STATE_IMMOBILIZING:
|
|
return "STATE_IMMOBILIZING"
|
|
case STATE_MOBILIZING:
|
|
return "STATE_MOBILIZING"
|
|
case STATE_MOBILIZED:
|
|
return "STATE_MOBILIZED"
|
|
}
|
|
return "missing"
|
|
}
|
|
|
|
type RedisImmobilizerMsg struct {
|
|
VIN string // VIN that we are modifying
|
|
State ImmobilizeState // How we are changing said state, which will affect how listening ditto's will manage
|
|
}
|
|
|
|
func (rim RedisImmobilizerMsg) MarshalBinary() ([]byte, error) {
|
|
return json.Marshal(rim)
|
|
}
|
|
|
|
func (rim RedisImmobilizerMsg) UnmarshalBinary(data []byte) error {
|
|
return json.Unmarshal(data, &rim)
|
|
}
|