packages feed

lifx-lan 0.5.0.1 → 0.5.1

raw patch · 5 files changed

+1928/−14 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Lifx.Lan: data LifxT m a
+ Lifx.Internal.Product: Features :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe (Word16, Word16) -> Bool -> Features
+ Lifx.Internal.Product: PartialFeatures :: Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe (Word16, Word16) -> Maybe Bool -> PartialFeatures
+ Lifx.Internal.Product: ProductInfo :: Word32 -> Text -> PartialFeatures -> [Upgrade] -> ProductInfo
+ Lifx.Internal.Product: Upgrade :: Word16 -> Word16 -> PartialFeatures -> Upgrade
+ Lifx.Internal.Product: VendorInfo :: Word32 -> Text -> Features -> [ProductInfo] -> VendorInfo
+ Lifx.Internal.Product: [$sel:buttons:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:buttons:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:chain:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:chain:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:color:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:color:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:defaults:VendorInfo] :: VendorInfo -> Features
+ Lifx.Internal.Product: [$sel:extendedMultizone:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:extendedMultizone:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:features:ProductInfo] :: ProductInfo -> PartialFeatures
+ Lifx.Internal.Product: [$sel:features:Upgrade] :: Upgrade -> PartialFeatures
+ Lifx.Internal.Product: [$sel:hev:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:hev:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:infrared:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:infrared:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:major:Upgrade] :: Upgrade -> Word16
+ Lifx.Internal.Product: [$sel:matrix:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:matrix:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:minor:Upgrade] :: Upgrade -> Word16
+ Lifx.Internal.Product: [$sel:multizone:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:multizone:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:name:ProductInfo] :: ProductInfo -> Text
+ Lifx.Internal.Product: [$sel:name:VendorInfo] :: VendorInfo -> Text
+ Lifx.Internal.Product: [$sel:pid:ProductInfo] :: ProductInfo -> Word32
+ Lifx.Internal.Product: [$sel:products:VendorInfo] :: VendorInfo -> [ProductInfo]
+ Lifx.Internal.Product: [$sel:relays:Features] :: Features -> Bool
+ Lifx.Internal.Product: [$sel:relays:PartialFeatures] :: PartialFeatures -> Maybe Bool
+ Lifx.Internal.Product: [$sel:temperatureRange:Features] :: Features -> Maybe (Word16, Word16)
+ Lifx.Internal.Product: [$sel:temperatureRange:PartialFeatures] :: PartialFeatures -> Maybe (Word16, Word16)
+ Lifx.Internal.Product: [$sel:upgrades:ProductInfo] :: ProductInfo -> [Upgrade]
+ Lifx.Internal.Product: [$sel:vid:VendorInfo] :: VendorInfo -> Word32
+ Lifx.Internal.Product: data Features
+ Lifx.Internal.Product: data PartialFeatures
+ Lifx.Internal.Product: data ProductInfo
+ Lifx.Internal.Product: data Upgrade
+ Lifx.Internal.Product: data VendorInfo
+ Lifx.Internal.Product: instance GHC.Show.Show Lifx.Internal.Product.Features
+ Lifx.Internal.Product: instance GHC.Show.Show Lifx.Internal.Product.PartialFeatures
+ Lifx.Internal.Product: instance GHC.Show.Show Lifx.Internal.Product.ProductInfo
+ Lifx.Internal.Product: instance GHC.Show.Show Lifx.Internal.Product.Upgrade
+ Lifx.Internal.Product: instance GHC.Show.Show Lifx.Internal.Product.VendorInfo
+ Lifx.Internal.ProductInfo: productInfo :: [VendorInfo]
+ Lifx.Lan: Features :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe (Word16, Word16) -> Bool -> Features
+ Lifx.Lan: LifxT :: StateT Word8 (ReaderT (Socket, Word32, Int) (ExceptT LifxError m)) a -> LifxT m a
+ Lifx.Lan: Product :: Text -> Word32 -> Features -> Product
+ Lifx.Lan: StateHostFirmware :: Word64 -> Word16 -> Word16 -> StateHostFirmware
+ Lifx.Lan: StateVersion :: Word32 -> Word32 -> StateVersion
+ Lifx.Lan: UnknownProductId :: Word32 -> LifxError
+ Lifx.Lan: UnknownVendorId :: Word32 -> LifxError
+ Lifx.Lan: [$sel:build:StateHostFirmware] :: StateHostFirmware -> Word64
+ Lifx.Lan: [$sel:buttons:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:chain:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:color:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:extendedMultizone:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:features:Product] :: Product -> Features
+ Lifx.Lan: [$sel:hev:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:infrared:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:matrix:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:multizone:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:name:Product] :: Product -> Text
+ Lifx.Lan: [$sel:product:StateVersion] :: StateVersion -> Word32
+ Lifx.Lan: [$sel:productId:Product] :: Product -> Word32
+ Lifx.Lan: [$sel:relays:Features] :: Features -> Bool
+ Lifx.Lan: [$sel:temperatureRange:Features] :: Features -> Maybe (Word16, Word16)
+ Lifx.Lan: [$sel:vendor:StateVersion] :: StateVersion -> Word32
+ Lifx.Lan: [$sel:versionMajor:StateHostFirmware] :: StateHostFirmware -> Word16
+ Lifx.Lan: [$sel:versionMinor:StateHostFirmware] :: StateHostFirmware -> Word16
+ Lifx.Lan: [GetHostFirmware] :: Message StateHostFirmware
+ Lifx.Lan: [GetVersion] :: Message StateVersion
+ Lifx.Lan: data Features
+ Lifx.Lan: data Product
+ Lifx.Lan: data StateHostFirmware
+ Lifx.Lan: data StateVersion
+ Lifx.Lan: getProductInfo :: MonadLifx m => Device -> m Product
+ Lifx.Lan: instance GHC.Classes.Eq Lifx.Lan.StateHostFirmware
+ Lifx.Lan: instance GHC.Classes.Eq Lifx.Lan.StateVersion
+ Lifx.Lan: instance GHC.Classes.Ord Lifx.Lan.StateHostFirmware
+ Lifx.Lan: instance GHC.Classes.Ord Lifx.Lan.StateVersion
+ Lifx.Lan: instance GHC.Generics.Generic Lifx.Lan.StateHostFirmware
+ Lifx.Lan: instance GHC.Generics.Generic Lifx.Lan.StateVersion
+ Lifx.Lan: instance GHC.Show.Show Lifx.Lan.Product
+ Lifx.Lan: instance GHC.Show.Show Lifx.Lan.StateHostFirmware
+ Lifx.Lan: instance GHC.Show.Show Lifx.Lan.StateVersion
+ Lifx.Lan: instance Lifx.Lan.MessageResult Lifx.Lan.StateHostFirmware
+ Lifx.Lan: instance Lifx.Lan.MessageResult Lifx.Lan.StateVersion
+ Lifx.Lan: instance Lifx.Lan.Response Lifx.Lan.StateHostFirmware
+ Lifx.Lan: instance Lifx.Lan.Response Lifx.Lan.StateVersion
+ Lifx.Lan: newtype LifxT m a

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for lifx-lan +## 0.5.1 -- 2021-12-12+- Implement `getProductInfo`.+- Expose `LifxT` constructor.+ ## 0.5.0 -- 2021-08-01 - Fix bug which was causing broadcasting not to work with messages that expect no response. 
lifx-lan.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               lifx-lan-version:            0.5.0.1+version:            0.5.1 license:            BSD-3-Clause license-file:       LICENSE author:             George Thomas@@ -16,14 +16,16 @@  library     exposed-modules:+        Lifx.Internal.Product+        Lifx.Internal.ProductInfo         Lifx.Lan     hs-source-dirs: src     ghc-options:         -Wall     build-depends:-        base ^>= 4.14,+        base ^>= {4.14, 4.15, 4.16},         binary ^>= 0.8.8,-        bytestring ^>= 0.10.8,+        bytestring ^>= {0.10.8, 0.11},         composition ^>= 1.0.2.1,         containers ^>= 0.6.2.1,         extra ^>= 1.7.1,@@ -33,8 +35,8 @@         random ^>= 1.2.0,         safe ^>= 0.3.19,         text ^>= 1.2.3,-        time ^>= 1.9.3,-        transformers ^>= 0.5.6,+        time ^>= {1.9.3, 1.10, 1.11, 1.12, 1.13},+        transformers ^>= {0.5.6, 0.6},     default-language: Haskell2010     default-extensions:         AllowAmbiguousTypes
+ src/Lifx/Internal/Product.hs view
@@ -0,0 +1,56 @@+-- | An exact mapping of the types in LIFX's `products.json`. It's easier to just use 'Lifx.Lan.getProductInfo'.+module Lifx.Internal.Product where++import Data.Text (Text)+import Data.Word (Word16, Word32)++data VendorInfo = VendorInfo+    { vid :: Word32+    , name :: Text+    , defaults :: Features+    , products :: [ProductInfo]+    }+    deriving (Show)++data ProductInfo = ProductInfo+    { pid :: Word32+    , name :: Text+    , features :: PartialFeatures+    , upgrades :: [Upgrade]+    }+    deriving (Show)++data PartialFeatures = PartialFeatures+    { hev :: Maybe Bool+    , color :: Maybe Bool+    , chain :: Maybe Bool+    , matrix :: Maybe Bool+    , relays :: Maybe Bool+    , buttons :: Maybe Bool+    , infrared :: Maybe Bool+    , multizone :: Maybe Bool+    , temperatureRange :: Maybe (Word16, Word16)+    , extendedMultizone :: Maybe Bool+    }+    deriving (Show)++data Features = Features+    { hev :: Bool+    , color :: Bool+    , chain :: Bool+    , matrix :: Bool+    , relays :: Bool+    , buttons :: Bool+    , infrared :: Bool+    , multizone :: Bool+    , temperatureRange :: Maybe (Word16, Word16)+    , extendedMultizone :: Bool+    }+    deriving (Show)++data Upgrade = Upgrade+    { major :: Word16+    , minor :: Word16+    , features :: PartialFeatures+    }+    deriving (Show)
+ src/Lifx/Internal/ProductInfo.hs view
@@ -0,0 +1,1669 @@+-- | This is auto-generated - see the "product-gen" script.+module Lifx.Internal.ProductInfo where++import Lifx.Internal.Product++productInfo :: [VendorInfo]+productInfo =+    [ VendorInfo+        { vid = 1+        , name = "LIFX"+        , defaults = Features+            { hev = False+            , color = False+            , chain = False+            , matrix = False+            , relays = False+            , buttons = False+            , infrared = False+            , multizone = False+            , temperatureRange = Nothing+            , extendedMultizone = False+            }+        , products =+            [ ProductInfo+                { pid = 1+                , name = "LIFX Original 1000"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 3+                , name = "LIFX Color 650"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 10+                , name = "LIFX White 800 (Low Voltage)"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 6500+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 11+                , name = "LIFX White 800 (High Voltage)"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 6500+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 15+                , name = "LIFX Color 1000"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 18+                , name = "LIFX White 900 BR30 (Low Voltage)"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 19+                , name = "LIFX White 900 BR30 (High Voltage)"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 20+                , name = "LIFX Color 1000 BR30"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 22+                , name = "LIFX Color 1000"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 27+                , name = "LIFX A19"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 28+                , name = "LIFX BR30"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 29+                , name = "LIFX A19 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 30+                , name = "LIFX BR30 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 31+                , name = "LIFX Z"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just True+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 32+                , name = "LIFX Z"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just True+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 77+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Nothing+                            , extendedMultizone = Just True+                            }+                        }+                    , Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 36+                , name = "LIFX Downlight"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 37+                , name = "LIFX Downlight"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 38+                , name = "LIFX Beam"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just True+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 77+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Nothing+                            , extendedMultizone = Just True+                            }+                        }+                    , Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 39+                , name = "LIFX Downlight White to Warm"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 40+                , name = "LIFX Downlight"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 43+                , name = "LIFX A19"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 44+                , name = "LIFX BR30"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 45+                , name = "LIFX A19 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 46+                , name = "LIFX BR30 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 2+                        , minor = 80+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 49+                , name = "LIFX Mini Color"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 50+                , name = "LIFX Mini White to Warm"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 6500+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 3+                        , minor = 70+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 51+                , name = "LIFX Mini White"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 2700+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 52+                , name = "LIFX GU10"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 53+                , name = "LIFX GU10"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 55+                , name = "LIFX Tile"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just True+                    , matrix = Just True+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 57+                , name = "LIFX Candle"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just True+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 59+                , name = "LIFX Mini Color"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 60+                , name = "LIFX Mini White to Warm"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 6500+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades =+                    [ Upgrade+                        { major = 3+                        , minor = 70+                        , features = PartialFeatures+                            { hev = Nothing+                            , color = Nothing+                            , chain = Nothing+                            , matrix = Nothing+                            , relays = Nothing+                            , buttons = Nothing+                            , infrared = Nothing+                            , multizone = Nothing+                            , temperatureRange = Just+                                ( 1500+                                , 9000+                                )+                            , extendedMultizone = Nothing+                            }+                        }+                    ]+                }+            , ProductInfo+                { pid = 61+                , name = "LIFX Mini White"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 2700+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 62+                , name = "LIFX A19"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 63+                , name = "LIFX BR30"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 64+                , name = "LIFX A19 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 65+                , name = "LIFX BR30 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 66+                , name = "LIFX Mini White"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 2700+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 68+                , name = "LIFX Candle"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just True+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 70+                , name = "LIFX Switch"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Just True+                    , buttons = Just True+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Nothing+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 71+                , name = "LIFX Switch"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Just True+                    , buttons = Just True+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Nothing+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 81+                , name = "LIFX Candle White to Warm"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2200+                        , 6500+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 82+                , name = "LIFX Filament Clear"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2100+                        , 2100+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 85+                , name = "LIFX Filament Amber"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2000+                        , 2000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 87+                , name = "LIFX Mini White"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 2700+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 88+                , name = "LIFX Mini White"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2700+                        , 2700+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 89+                , name = "LIFX Switch"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Just True+                    , buttons = Just True+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Nothing+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 90+                , name = "LIFX Clean"+                , features = PartialFeatures+                    { hev = Just True+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 91+                , name = "LIFX Color"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 92+                , name = "LIFX Color"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 93+                , name = "LIFX A19 US"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 94+                , name = "LIFX BR30"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 96+                , name = "LIFX Candle White to Warm"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2200+                        , 6500+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 97+                , name = "LIFX A19"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 98+                , name = "LIFX BR30"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 99+                , name = "LIFX Clean"+                , features = PartialFeatures+                    { hev = Just True+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 100+                , name = "LIFX Filament Clear"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2100+                        , 2100+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 101+                , name = "LIFX Filament Amber"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 2000+                        , 2000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 109+                , name = "LIFX A19 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 110+                , name = "LIFX BR30 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 111+                , name = "LIFX A19 Night Vision"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 112+                , name = "LIFX BR30 Night Vision Intl"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just True+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just True+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 113+                , name = "LIFX Mini WW US"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            , ProductInfo+                { pid = 114+                , name = "LIFX Mini WW Intl"+                , features = PartialFeatures+                    { hev = Nothing+                    , color = Just False+                    , chain = Just False+                    , matrix = Just False+                    , relays = Nothing+                    , buttons = Nothing+                    , infrared = Just False+                    , multizone = Just False+                    , temperatureRange = Just+                        ( 1500+                        , 9000+                        )+                    , extendedMultizone = Nothing+                    }+                , upgrades = []+                }+            ]+        }+    ]
src/Lifx/Lan.hs view
@@ -28,7 +28,7 @@     HSBK (..),     Lifx,     runLifx,-    LifxT,+    LifxT (LifxT),     runLifxT,     LifxError (..),     MonadLifx (..),@@ -36,9 +36,16 @@     -- * Responses     StateService (..),     Service (..),+    StateHostFirmware (..),     StatePower (..),+    StateVersion (..),     LightState (..), +    -- ** Product info+    getProductInfo,+    Product (..),+    Features (..),+     -- * Low-level     deviceFromAddress,     encodeMessage,@@ -46,6 +53,7 @@     unLifxT, ) where +import Control.Applicative import Control.Monad import Control.Monad.Except import Control.Monad.Extra@@ -54,10 +62,10 @@ import Control.Monad.Trans.Maybe import Data.Either.Extra import Data.Fixed-import Data.Foldable+import Data.Foldable hiding (product) import Data.Function import Data.Functor-import Data.List+import Data.List hiding (product) import Data.Maybe import Data.Tuple.Extra import Data.Word@@ -72,6 +80,7 @@     getWord16le,     getWord32le,     getWord64be,+    getWord64le,     getWord8,     runGetOrFail,     skip,@@ -88,8 +97,9 @@ import Data.ByteString qualified as BS import Data.ByteString.Lazy qualified as BL import Data.List.NonEmpty (NonEmpty)-import Data.Map (Map)+import Data.Map (Map, (!?)) import Data.Map.Strict qualified as Map+import Data.Text (Text) import Data.Time (     NominalDiffTime,     diffUTCTime,@@ -117,6 +127,12 @@ import System.Random (randomIO) import System.Timeout (timeout) +import Lifx.Internal.Product+import Lifx.Internal.ProductInfo++--TODO RecordDotSyntax can make this and other hiding unnecessary (we could also use "id" instead of "productId"...)+import Prelude hiding (product)+ {- Device -}  -- | A LIFX device, such as a bulb.@@ -187,10 +203,14 @@     -- | https://lan.developer.lifx.com/docs/querying-the-device-for-data#getservice---packet-2     -- (you shouldn't need this - use 'discoverDevices')     GetService :: Message StateService+    -- | https://lan.developer.lifx.com/docs/querying-the-device-for-data#gethostfirmware---packet-14+    GetHostFirmware :: Message StateHostFirmware     -- | https://lan.developer.lifx.com/docs/querying-the-device-for-data#getpower---packet-20     GetPower :: Message StatePower     -- | https://lan.developer.lifx.com/docs/changing-a-device#setpower---packet-21     SetPower :: Bool -> Message ()+    -- | https://lan.developer.lifx.com/docs/querying-the-device-for-data#getversion---packet-32+    GetVersion :: Message StateVersion     -- | https://lan.developer.lifx.com/docs/querying-the-device-for-data#getcolor---packet-101     GetColor :: Message LightState     -- | https://lan.developer.lifx.com/docs/changing-a-device#setcolor---packet-102@@ -218,12 +238,32 @@     }     deriving (Eq, Ord, Show, Generic) +-- | https://lan.developer.lifx.com/docs/information-messages#statehostfirmware---packet-15+data StateHostFirmware = StateHostFirmware+    { -- | The timestamp of the firmware that is on the device as an epoch+      build :: Word64+    , -- | The minor component of the firmware version+      versionMinor :: Word16+    , -- | The major component of the firmware version+      versionMajor :: Word16+    }+    deriving (Eq, Ord, Show, Generic)+ -- | https://lan.developer.lifx.com/docs/information-messages#statepower---packet-22 newtype StatePower = StatePower     { power :: Word16     }     deriving (Eq, Ord, Show, Generic) +-- | https://lan.developer.lifx.com/docs/information-messages#stateversion---packet-33+data StateVersion = StateVersion+    { -- | For LIFX products this value is 1. There may be devices in the future with a different vendor value.+      vendor :: Word32+    , -- | The product id of the device. The available products can be found in our Product Registry.+      product :: Word32+    }+    deriving (Eq, Ord, Show, Generic)+ -- | https://lan.developer.lifx.com/docs/information-messages#lightstate---packet-107 data LightState = LightState     { hsbk :: HSBK@@ -240,6 +280,8 @@     | WrongSender Device HostAddress -- expected, then actual     | UnexpectedSockAddrType SockAddr     | UnexpectedPort PortNumber+    | UnknownVendorId Word32+    | UnknownProductId Word32     deriving (Eq, Ord, Show, Generic)  {- Message responses -}@@ -325,6 +367,30 @@             maybe (fail $ "port out of range: " <> show x) pure $ fromIntegralSafe x         pure StateService{..} instance MessageResult StateService+instance Response StateHostFirmware where+    expectedPacketType = 15+    messageSize = 20+    getBody = do+        build <- getWord64le+        skip 8+        versionMinor <- getWord16le+        versionMajor <- getWord16le+        pure StateHostFirmware{..}+instance MessageResult StateHostFirmware+instance Response StatePower where+    expectedPacketType = 22+    messageSize = 2+    getBody = StatePower <$> getWord16le+instance MessageResult StatePower+instance Response StateVersion where+    expectedPacketType = 33+    messageSize = 20+    getBody = do+        vendor <- getWord32le+        product <- getWord32le+        skip 4+        pure StateVersion{..}+instance MessageResult StateVersion instance Response LightState where     expectedPacketType = 107     messageSize = 52@@ -336,11 +402,6 @@         skip 8         pure LightState{..} instance MessageResult LightState-instance Response StatePower where-    expectedPacketType = 22-    messageSize = 2-    getBody = StatePower <$> getWord16le-instance MessageResult StatePower  -- all `Message` response types are instances of `MessageResult` --TODO ImpredicativeTypes:@@ -348,8 +409,10 @@ msgResWitness :: Message r -> Dict (MessageResult r) msgResWitness = \case     GetService{} -> Dict+    GetHostFirmware{} -> Dict     GetPower{} -> Dict     SetPower{} -> Dict+    GetVersion{} -> Dict     GetColor{} -> Dict     SetColor{} -> Dict     SetLightPower{} -> Dict@@ -531,6 +594,12 @@             , packetType = 2             , ..             }+    GetHostFirmware{} ->+        Header+            { size = headerSize+            , packetType = 14+            , ..+            }     GetPower{} ->         Header             { size = headerSize@@ -543,6 +612,12 @@             , packetType = 21             , ..             }+    GetVersion{} ->+        Header+            { size = headerSize+            , packetType = 32+            , ..+            }     GetColor{} ->         Header             { size = headerSize@@ -571,9 +646,11 @@ putMessagePayload :: Message r -> Put putMessagePayload = \case     GetService -> mempty+    GetHostFirmware -> mempty     GetPower -> mempty     SetPower b ->         putWord16le if b then maxBound else minBound+    GetVersion -> mempty     GetColor -> mempty     SetColor HSBK{..} d -> do         putWord8 0@@ -585,6 +662,112 @@     SetLightPower b d -> do         putWord16le if b then maxBound else minBound         putWord32le $ nominalDiffTimeToInt @Milli d++{- Product info -}++productInfoMap :: Map Word32 (Features, Map Word32 ProductInfo)+productInfoMap =+    Map.fromList $+        productInfo <&> \VendorInfo{..} ->+            ( vid+            ,+                ( defaults+                , Map.fromList $ (pid &&& id) <$> products+                )+            )++-- | Information about a particular LIFX product.+data Product = Product+    { name :: Text+    , productId :: Word32+    , features :: Features+    }+    deriving (Show)++-- | Ask a device for it's vendor and product ID, and look up info on it from the official database.+getProductInfo :: MonadLifx m => Device -> m Product+getProductInfo dev = do+    StateHostFirmware{..} <- sendMessage dev GetHostFirmware+    StateVersion{..} <- sendMessage dev GetVersion+    case productInfoMap !? vendor of+        Nothing -> lifxThrow $ UnknownVendorId vendor+        Just (defaults, products) -> case products !? product of+            Nothing -> lifxThrow $ UnknownProductId product+            Just ProductInfo{features = originalFeatures, ..} ->+                pure+                    Product+                        { name+                        , productId = product+                        , features =+                            completeFeatures defaults $+                                foldl+                                    ( \old Upgrade{..} ->+                                        if (versionMajor, versionMinor) >= (major, minor)+                                            then addFeatures features old+                                            else old+                                    )+                                    originalFeatures+                                    upgrades+                        }+  where+    --TODO RecordDotSyntax+    completeFeatures+        Features+            { ..+            }+        PartialFeatures+            { hev = maybe_hev+            , color = maybe_color+            , chain = maybe_chain+            , matrix = maybe_matrix+            , relays = maybe_relays+            , buttons = maybe_buttons+            , infrared = maybe_infrared+            , multizone = maybe_multizone+            , temperatureRange = maybe_temperatureRange+            , extendedMultizone = maybe_extendedMultizone+            } =+            Features+                { hev = fromMaybe hev maybe_hev+                , color = fromMaybe color maybe_color+                , chain = fromMaybe chain maybe_chain+                , matrix = fromMaybe matrix maybe_matrix+                , relays = fromMaybe relays maybe_relays+                , buttons = fromMaybe buttons maybe_buttons+                , infrared = fromMaybe infrared maybe_infrared+                , multizone = fromMaybe multizone maybe_multizone+                , temperatureRange = maybe_temperatureRange <|> temperatureRange+                , extendedMultizone = fromMaybe extendedMultizone maybe_extendedMultizone+                }+    -- left-biased+    addFeatures+        PartialFeatures+            { ..+            }+        PartialFeatures+            { hev = old_hev+            , color = old_color+            , chain = old_chain+            , matrix = old_matrix+            , relays = old_relays+            , buttons = old_buttons+            , infrared = old_infrared+            , multizone = old_multizone+            , temperatureRange = old_temperatureRange+            , extendedMultizone = old_extendedMultizone+            } =+            PartialFeatures+                { hev = hev <|> old_hev+                , color = color <|> old_color+                , chain = chain <|> old_chain+                , matrix = matrix <|> old_matrix+                , relays = relays <|> old_relays+                , buttons = buttons <|> old_buttons+                , infrared = infrared <|> old_infrared+                , multizone = multizone <|> old_multizone+                , temperatureRange = temperatureRange <|> old_temperatureRange+                , extendedMultizone = extendedMultizone <|> old_extendedMultizone+                }  {- Util -}