Jump to content
C4 Forums | Control4

BuffaloC4

c4Forums Member
  • Posts

    134
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by BuffaloC4

  1. 23 minutes ago, Rexabyte said:

    I haven't touched the API in question but I can hopefully explain the time things can take and libraries.

    A while ago I wanted to create an Xbox driver that works over the SmartGlass protocol. While this would be relatively easy if you had the SDK that Microsoft provides it is much more difficult in a sandboxed environment (Control4) where you cannot use the SDK provided by Microsoft. Instead you need to work with the raw protocol (bits and bytes) and write all of the logic required just to even communicate to the Xbox. Sometimes you can find opensource MIT licensed code to do portions of what you need, other times you need to write it yourself.

    So what would it take to write everything required where the libraries don't exist in Control4? Let's start with JUST the crypto portion: https://openxbox.org/smartglass-documentation/cryptography/#key-exchange

    • On Discovery, the console responds with a Discovery Response including a certificate, this certificate holds the console's public key.
    • The client generates elliptic curve and derives the shared secret with console's public key using ECDH and a randomly generated public/private keypair
    • The shared secret is salted using static salts, see KDF Salts
    • The salted shared secret is hashed using SHA-512
    • The salted & hashed shared secret is split into the following individual keys:
    • bytes 0-16: Encryption key (AES-128-CBC)
    • bytes 16-32: Initialization Vector key (AES-128-CBC)
    • bytes 32-64: Hashing key (HMAC-SHA-256)
    • The client's public key is sent inside the Connect Request message to the console

    First things first we need to get the public key from the certificate. So we need to parse out the response and format it. It's received in an ASN. The following code (incomplete, needs to support more types, also using a custom library, BitHelper, to read bits and bytes) is used just to parse the ASN to get the public key used in step 2. After that we still need to do encryption using ECDH, which if not supported in Control4's encryption methods also needs to be written or sourced from somewhere. This can go on and on.
     

    
    ASN = (function()
        local class = {}; class.__index = class
    
        local Types = {
            BOOLEAN  = 0x01,
            INTEGER  = 0x02,
            STRING   = 0x03,
            OCTET    = 0x04,
            NULL     = 0x05,
            OBJECT   = 0x06,
            UTF8String = 0x0C,
            IA5STRING= 0x16,
            SEQUENCE = 0x30,
            SET      = 0x31,
        }
    
        class.Map = {
            [0x01] = "DecodeBoolean",
            [0x02] = "DecodeInteger",
            [0x03] = "DecodeString",
            [0x04] = "DecodeOctet",
            [0x05] = "DecodeNull",
            [0x06] = "DecodeObject",
            [0x0C] = "DecodeUTF8String",
            [0x13] = "DecodeUTF8String",
            [0x16] = "DecodeIA5String",
            [0x17] = "DecodeUTCTime",
            [0x30] = "DecodeSequence",
            [0x31] = "DecodeSet",
        }
    
        class.Class = {
            ["Universal"] = 0,
            ["Application"] = 1,
            ["Context"] = 2,
            ["Private" ] = 3
        }
    
        function class.DecodeSet(data, pos)
            Logger.Trace("ASN.DecodeSet: " .. pos)
            pos, l = class.DecodeLength(data, pos)
            pos, d = BitHelper.GetString(data, pos, l)
    
            local p, obj = class.Parse(d)
    
            return pos, obj
        end
    
        function class.DecodeOctet(data, pos)
            local l,d
    
            pos, l = class.DecodeLength(data, pos)
            pos, d = BitHelper.GetString(data, pos, l)
    
            return pos, d
        end
    
        function class.DecodeUTCTime(data, pos)
            Logger.Trace("ASN.DecodeUTCTime")
    
            pos, length = class.DecodeLength(data, pos)
    
            --print("STRING LENGTH: " .. length)
    
            pos, str = BitHelper.GetString(data, pos, length)
    
            --print("STRING: " .. str)
    
            return pos, str
        end
    
        function class.DecodeString(data, pos)
            Logger.Trace("ASN.DecodeString")
    
            pos, length = class.DecodeLength(data, pos)
    
            --print("STRING LENGTH: " .. length)
    
            pos, str = BitHelper.GetString(data, pos, length)
    
            --print("STRING: " .. str)
    
            return pos, str
        end
    
        function class.DecodeUTF8String(data, pos)
            Logger.Trace("ASN.DecodeUTF8String")
    
            pos, length = class.DecodeLength(data, pos)
    
            --print("STRING LENGTH: " .. length)
    
            pos, str = BitHelper.GetString(data, pos, length)
    
            --print("STRING: " .. str)
    
            return pos, str
        end
    
        function class.DecodeLength(data, pos)
            Logger.Trace("ASN.DecodeLength")
    
            local length = nil
    
            pos, length = BitHelper.GetInt8(data, pos)
    
            local isLong = bit.band(length, 0x80) ~= 0
    
            --print("LONG: " .. tostring(isLong))
    
            if (isLong) then
                local bytes = bit.band(length, 0x7F)
    
                Logger.Debug("BYTES: " .. bytes)
                Logger.Debug(hexdump(string.sub(data, pos, pos + bytes - 1)))
    
                if (bytes == 1) then
                    pos, length = BitHelper.GetInt8(data, pos)
                elseif (bytes == 2) then
                    pos, length = BitHelper.GetInt16(data, pos)
                elseif (bytes == 4) then
                    pos, length = BitHelper.GetInt32(data, pos)
                else
                    Logger.Error("BAD LENGTH")
                end
    
                --print("LENGTH: " .. length)
            else
                Logger.Debug("LENGTH: " .. length)
                Logger.Debug(hexdump(string.sub(data, pos - 1, pos)))
            end
    
            return pos, length
        end
    
        function class.DecodeSequence(data, pos)
            Logger.Trace("ASN.DecodeSequence: " .. pos)
            --print(hexdump(string.sub(data, pos)))
    
            pos, l = class.DecodeLength(data, pos)
            pos, d = BitHelper.GetString(data, pos, l)
    
            local p, obj = class.Parse(d)
    
            return pos, obj
        end
    
        function class.DecodeSequenceOf()
    
        end
    
        function class.DecodeInteger(data, pos)
            Logger.Trace("ASN.DecodeInteger")
    
            local start = pos
    
            pos, length = class.DecodeLength(data, pos)
    
            if (length == 1) then
                return BitHelper.GetInt8(data, pos)
            elseif (length == 2) then
                return BitHelper.GetInt16(data, pos)
            elseif (length == 4) then
                return BitHelper.GetInt32(data, pos)
            else
                return BitHelper.GetString(data, pos, length)
            end
        end
    
        function class.DecodeContext(data, pos)
            Logger.Trace("ASN.DecodeContext")
    
            local length, d
    
            pos, length = class.DecodeLength(data, pos)
            pos, d = BitHelper.GetString(data, pos, length)
    
            local _, obj = class.Parse(d)
    
            return pos, obj
        end
    
        function class.DecodeObject(data, pos)
            Logger.Trace("ASN.DecodeObject")
    
            local length = 0
    
            pos, length = class.DecodeLength(data, pos)
    
            local d = string.sub(data, pos, pos + length)
    
            local p, firstByte = BitHelper.GetInt8(d)
    
            local firstDigit = firstByte / 40;
            local secondDigit = firstByte % 40;
            local nodes = { firstDigit, secondDigit }
    
            -- TODO: Determine OID value
    
            return pos + length, d
        end
    
        function class.DecodeNull(data, pos)
            pos, length = class.DecodeLength(data, pos)
    
            return pos, false
        end
    
        function class.DecodeBoolean(data, pos)
            Logger.Trace("ASN.DecodeBoolean")
    
            pos, length = class.DecodeLength(data, pos)
            pos, d = BitHelper.GetInt8(data, pos)
    
            return pos, d
        end
    
        function class.DecodeChoice()
    
        end
    
        function class.Parse(certificate, pos)
            Logger.Trace("ASN.Parse")
    
            local pos = pos or 1
            local limit = 1
            local obj = {}
    
            while (pos < #certificate) do
                local t, l, d
    
                pos, t = BitHelper.GetInt8(certificate, pos)
    
                local f = bit.rshift(bit.band(t, 0x20), 5)
                local c = bit.rshift(bit.band(t, 0xC0), 6)
    
                local method = class.Map[t]
    
                if (method and class[method]) then
                    Logger.Trace(method)
    
                    pos, d = class[method](certificate, pos)
    
                    obj[#obj + 1] = d
                else
                    if (c == class.Class.Context) then
                        pos, d = class.DecodeContext(certificate, pos)
                    else
                        Logger.Error("BAD METHOD: " .. t)
                    end
                end
            end
            return pos, obj
        end
    
        local mt = {
            __call = function(self)
                local instance = {}
    
                setmetatable(instance, class)
    
                return instance
            end,
        }
    
        setmetatable(class, mt)
    
        return class
    end) ()



     

    Did you ever get this working? 
    I bet people would employ you to do an Xbox driver for them. I know I would. 

  2. I have a 6x6 Kramer Matrix running 4 x 50ft runs and 2x 75 ft runs. I feel like I may have gotten somewhat lucky with my experience , but I assume you'll get away with a 20 ft run. Many, many, many people will try to influence you to go the balun route. 

  3. Definitely go with video matrix. What's the point of having such a unified solution and not have the ability to sync up all tv's in the house. 
     

    the feature is a must for parties. Even guests using my bathroom get to view the music videos that I play during gathering. 
     

    I also only have to rent one cable box from my provider. 
     

    also TVs that sync is also great while cleaning the house. Put on a show or video throughout and enjoy it in each room. Very wasteful, but hey... c4....

  4. Is there a temperature ceiling or max reading when using an external thermistor with a z2io. I know the internal thermistor max is like 105, but I'd like to get a heavy duty external one to measure something that gets to like 300/400 degrees. 
     

    it is to ensure a clients pot (medicine) smoking device gets turned off.
     

    thanks for any and all feedback. 

  5. I tried to go the consumer route and grab z-wave locks and identify them with some online kwikset z wave driver... no surprise... they don't identify correctly. (Ea-3 w/ dongle) 

    while work is being done in these areas I really need replacement zigbee deadbolts. 
     

    or if anyone might understand why my current locks keep saying they have been identified but to a driver that does not match in pro. 
     

    Thanks! 
     

    I'm in western New York area. 

  6. Just now, msgreenf said:

    sorry, ask your question again - you can have 2 250's in a project no problem.  (i have an extra to sell cheap)

    Thanks for your time, Msgreenf, what os is required to have a project with 2x HC-250 and no 800. 
     

    I don't want to have to buy my parents an 800 just to control their minuscule setup. 

     

    They already have 1 HC-250 and I'll add the 2nd tomorrow if it's possible.
     

    unfortunately I already got a 250 and SR260 from eBay for nearly nothing. 

     

    thanks again, 

    The Madia's

  7. On 2/7/2020 at 5:19 PM, Matt Lowe said:

    OS 3. gives you a lot more customization options over the app is one that got a major overhaul. 

    My nearly 80 year old parents have no need for OS3. (I love it) Can I add a second HC-250 onto a system directed by an HC-250?

    Does anyone recall which OS allowed for this ? I remember when I started with C4, a 800 was necessary to "enslave" HC-250s

    however, I somewhat remember a loosening of restrictions on 250s when OS3 came out. 
     

    ugh. I really don't want to buy them an 800. Their system is minuscule. 
     

    thanks 

    JM

  8. 3 hours ago, WholeHomeControl said:

    I’ve seen this issue as well and don’t have a fix. 
     

    As a workaround, however, this might help:

    Set the EA-3 audio output as the audio end point for a hidden room. Now, you have a way programmatically to get that volume level back up to 100% (ie custom button first plays EA3 source in room and then set volume to 100%. Then turn off room.)

    I tried to replicate such binding in my personal system. Didn't expose the set volume value. 
     

    Anyone else experiencing this? Enough support to hear from c4 maybe? 

  9. Occasionally I go to play pandora or some other native service on my EA-3 analog output -> to matrix amp and I get no sound.

    every single time the problem has been that the output switches to 0 volume. (not on navigators, but in the properties of my EA-3).

    happens once a week. I even tried making a custom button to just circumvent the problem, but I don't believe the programming is exposed. 
     

    Side note: the controller also occasionally requires a reboot to get IO board working. Maybe 4 times a year. 
     

    unit was part of the first shipment of EAs so likely no warranty. 
     

    All thoughts and considerations are appreciated, 

     

    JM
     

     

  10. Does anyone have a wiring diagram that would explain how to wire 2 dvc speakers to a single amplifier LR zone. Both speakers need signal from both L and R? 
     

    cant find a diagram online anywhere. 
     

    thanks in advance! 

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.