Jump to content
C4 Forums | Control4

Rexabyte

c4Forums Member
  • Posts

    236
  • Joined

  • Last visited

  • Days Won

    8

Rexabyte last won the day on January 30 2021

Rexabyte had the most liked content!

2 Followers

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

4,555 profile views

Rexabyte's Achievements

  1. Recent models require connections to port 3001 (Secure Websocket) as they closed the original port that the driver used. There is a version of the driver available that supports most recent models that require port 3001. If your TV model mentions WebOS odds are the driver will work. 4.X versions of our driver will work on older models, 5.X for anything more recent.
  2. Not sure what that other driver did exactly, but I wrote something a bit ago that may do what you need if you're just trying to share a serial connection: https://github.com/annex4-inc/control4-serial-shim You should be able to download the .c4z file in the release section.
  3. All the application IDs are being set properly to what you entered in the form. Everything else looks correct in the XML as well, I'm under the assumption that the IDs are incorrect.
  4. JSON_APP_DATA = [[{ "serviceIds": { "UM_SAMSUNG2017": "gcn+", "UM_SAMSUNG2021": "gcn+", "UM_AMAZON": "com.playsportsnetwork.tourmalet", "UM_SONY_TV": "GCN Player - Live Player Streaming", "UM_NV_SHIELD": "com.playsportsnetwork.tourmalet" }, "appName": "GCN+" }]] The "UM_AMAZON" ID is 'com.playsportsnetwork.tourmalet', not 'com.playsportsnetwork.tourmalet.tv'. I haven't checked the actual application ID but is that correct?
  5. This is just the Netflix one (1:1 match with the one in the database.) Should be um_gcn+.c4z?
  6. Send me the resulting .c4z file and I'll see what's up with it. If there's a bug somewhere I'll release a hotfix.
  7. Proxy ID is the ID of an actual proxy (television, security_panel, light_v2 etc.) attached to a driver, there can be several. If you wanted a variable in relation to a light for example you would need to target the Proxy ID. Device ID is the ID of encompassing device (driver). Some devices do not have a proxy, these should be flagged with a combo element in the XML portion of the driver meaning they are both a proxy & device driver and share an ID (Device ID). If I create a variable in code from a driver the resulting variable gets placed on the device (use Device ID to reference). In the composer tree it's typical that the first proxy device is merged into the encompassing device visually and it doesn't make its own branch. A good example are lights with keypads. The light_v2 proxy gets displayed on the device and the keypad gets branched to a new node. @South Africa C4 user Hope this helps!
  8. https://www.control4.com/help/bin/moip/900-ig/Content/Ryff to MoIP.htm Any of the drivers mentioned above would experience the same issue.
  9. What features are you looking for? What issues have you had?
  10. @mstafford388 Sorry you thought annex4 was gone. Been busy. I decided to move the entire infrastructure and rebuild it on AWS. Devices now talk directly with AWS IoT Core (MQTT). That solved a lot of maintenance and scale related stuff and the cost will end up being cheaper than spinning up new servers to support more controllers real-time. Leaves me more time to focus on making drivers, and not supporting the infrastructure around serving drivers & licenses. There's a new frontend facelift as well. I moved away from Meteor as it didn't scale well. Now using a static site created with Vue served over CloudFront. It talks to AWS AppSync for real-time pub/sub and its GraphQL API. Uses the latest Stripe checkout stuff as well, which is visually a major improvement over what we have now. Overall the new infrastructure is largely cloud services and usually 'serverless' which takes a lot of weight off me for maintenance related stuff. Images attached are just development stuff. Removed the required training going forward on the new site as well. I never liked it, always thought it was more of a hinderance to onboarding new users. The driver connecting to the platform is a 1 click install now as well as it gets an embedded certificate for licensing and authentication. You simply create the project on the platform and download the driver created for it, not much you can do wrong. Filenames no longer matter either.
  11. Not gone. Not sure who told you that. Bunch of changes coming September/October including some new drivers. All of our drivers at the moment are technically just served over Amazon S3 and we're not currently generating presigned URLs for download. Technically anyone with access can give you the link. I don't want to post them in a public forum but I'll PM them to you shortly.
  12. I did publish that extension and what I posted above will be an entirely new extension. It's such a major overhaul that I'll leave the old one as a lightweight completion extension for the functions and developers that have their own build methods. The new one is opinionated and requires a certain project structure for building the driver, but it does come with quite a few benefits. Here's some source code of an example driver: https://github.com/annex4-inc/generic-camera-driver You'll notice there is no driver.xml file, it's been split apart into the components folder and a smaller JSON object in the package.json file. EDIT: Should also mention the extension can import .c4z files to migrate to the expected project structure.
  13. I'm in the process of updating my VSCode extension I started long ago. I actually just added support for updating Lua script today after Ryan's comment. The formatting of the driver is quite different and there's no modifications inside of XML anymore. Most sections are broken out into JSON files for their specific purposes (properties, commands, events, connections, etc) and provide a webview for modification, you can still edit the underlying JSON file as well (backed by JSON schemas) I've also been able to include some improvements for things that bothered me, for example you can now specify the amount of HDMI connections you want to generate rather than copy pasting a bunch of XML blocks: Properties & Webview example: Auto completion of functions: Signature helpers: All that being said I still haven't pushed a release as there are some issues to work out around the UI capability section. Repository here: https://github.com/annex4-inc/vscode-control4-ext
  14. It was put on the back burner as we took on some non Control4 related projects. We never revisited it afterwards as the Series X released and it doesn't work over the same local communication method, it requires an internet connection and uses xCloud.
  15. 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) ()
×
×
  • Create New...

Important Information

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