Last active
August 29, 2015 14:07
-
-
Save bentayloruk/7392b1659903d540163f to your computer and use it in GitHub Desktop.
One of many Sonos services in the F# type system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Peelio.ZonePlayer.ZoneGroupTopology | |
open System | |
open System.Linq | |
open System.Xml.Linq | |
open Peelio | |
/// Union types for those state vars with a set of allowed values. | |
type A_ARG_TYPE_UpdateType = | All | Software | |
with | |
override __.ToString() = match __ with | All -> "All" | Software -> "Software" | |
static member Parse(x:string) = match x with | "All" -> All | "Software" -> Software | _ -> failwith "Cannot parse value." | |
type A_ARG_TYPE_UnresponsiveDeviceActionType = | Remove | VerifyThenRemoveSystemwide | |
with | |
override __.ToString() = match __ with | Remove -> "Remove" | VerifyThenRemoveSystemwide -> "VerifyThenRemoveSystemwide" | |
static member Parse(x:string) = match x with | "Remove" -> Remove | "VerifyThenRemoveSystemwide" -> VerifyThenRemoveSystemwide | _ -> failwith "Cannot parse value." | |
type A_ARG_TYPE_Origin = | Healthcheck | Server | User | |
with | |
override __.ToString() = match __ with | Healthcheck -> "Healthcheck" | Server -> "Server" | User -> "User" | |
static member Parse(x:string) = match x with | "Healthcheck" -> Healthcheck | "Server" -> Server | "User" -> User | _ -> failwith "Cannot parse value." | |
/// Record type to hold all state values. | |
type ZoneGroupTopologyState = { | |
AvailableSoftwareUpdate : String | |
ZoneGroupState : String | |
ThirdPartyMediaServersX : String | |
AlarmRunSequence : String | |
ZoneGroupName : String | |
ZoneGroupID : String | |
ZonePlayerUUIDsInGroup : String | |
} | |
// Action response types (only for responses containing values). | |
type CheckForUpdateResponse = { UpdateItem : String } | |
type SubmitDiagnosticsResponse = { DiagnosticID : UInt32 } | |
type ZoneGroupAttributesResponse = { CurrentZoneGroupName : String; CurrentZoneGroupID : String; CurrentZonePlayerUUIDsInGroup : String } | |
type ZoneGroupStateResponse = { ZoneGroupState : String } | |
/// ZoneGroupTopology Service | |
type ZoneGroupTopologySvc private (device:Device, service:Service) = | |
inherit Peelio.CpService(device, service) | |
let (state:ZoneGroupTopologyState option ref) = ref None | |
let onStateChange = Event<ZoneGroupTopologyState>() | |
static let svcPath = DevicePart("ZonePlayer", 1, ServicePart("ZoneGroupTopology", 1)) | |
static member TryCreate(device) = | |
match Upnp.tryFindService svcPath device with | |
| Some(svc) -> Some(ZoneGroupTopologySvc(device, svc)) | |
| None -> None | |
override __.OnUpnpEvent(eventXml:string) = | |
let propMap = Upnp.eventPropStateMap eventXml | |
match !state with | |
| Some(s) -> ()//TODO update | |
| None -> | |
let newState = | |
{ | |
AvailableSoftwareUpdate = propMap.["AvailableSoftwareUpdate"] | |
ZoneGroupState = propMap.["ZoneGroupState"] | |
ThirdPartyMediaServersX = propMap.["ThirdPartyMediaServersX"] | |
AlarmRunSequence = propMap.["AlarmRunSequence"] | |
ZoneGroupName = propMap.["ZoneGroupName"] | |
ZoneGroupID = propMap.["ZoneGroupID"] | |
ZonePlayerUUIDsInGroup = propMap.["ZonePlayerUUIDsInGroup"] | |
} | |
state := Some newState | |
onStateChange.Trigger(newState) | |
[<CLIEvent>] | |
member __.StateChanged = onStateChange.Publish | |
member __.CheckForUpdate(updateType : A_ARG_TYPE_UpdateType, cachedOnly : Boolean, version : String) = | |
async { | |
let vals = ["UpdateType", updateType.ToString();"CachedOnly", cachedOnly.ToString();"Version", version.ToString();] | |
let! resValMapOrEx = __.DoAction("CheckForUpdate", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2({ CheckForUpdateResponse.UpdateItem = valMap.Item("UpdateItem") }) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.BeginSoftwareUpdate(updateURL : String, flags : UInt32, extraOptions : String) = | |
async { | |
let vals = ["UpdateURL", updateURL.ToString();"Flags", flags.ToString();"ExtraOptions", extraOptions.ToString();] | |
let! resValMapOrEx = __.DoAction("BeginSoftwareUpdate", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2(()) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.ReportUnresponsiveDevice(deviceUUID : String, desiredAction : A_ARG_TYPE_UnresponsiveDeviceActionType) = | |
async { | |
let vals = ["DeviceUUID", deviceUUID.ToString();"DesiredAction", desiredAction.ToString();] | |
let! resValMapOrEx = __.DoAction("ReportUnresponsiveDevice", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2(()) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.ReportAlarmStartedRunning() = | |
async { | |
let vals = [] | |
let! resValMapOrEx = __.DoAction("ReportAlarmStartedRunning", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2(()) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.SubmitDiagnostics(includeControllers : Boolean, t : A_ARG_TYPE_Origin) = | |
async { | |
let vals = ["IncludeControllers", includeControllers.ToString();"Type", t.ToString();] | |
let! resValMapOrEx = __.DoAction("SubmitDiagnostics", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2({ SubmitDiagnosticsResponse.DiagnosticID = Convert.ChangeType(valMap.Item("DiagnosticID"), typeof<UInt32>) :?> UInt32 }) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.RegisterMobileDevice(mobileDeviceName : String, mobileDeviceUDN : String, mobileIPAndPort : String) = | |
async { | |
let vals = ["MobileDeviceName", mobileDeviceName.ToString();"MobileDeviceUDN", mobileDeviceUDN.ToString();"MobileIPAndPort", mobileIPAndPort.ToString();] | |
let! resValMapOrEx = __.DoAction("RegisterMobileDevice", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2(()) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.GetZoneGroupAttributes() = | |
async { | |
let vals = [] | |
let! resValMapOrEx = __.DoAction("GetZoneGroupAttributes", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2({ ZoneGroupAttributesResponse.CurrentZoneGroupName = valMap.Item("CurrentZoneGroupName"); CurrentZoneGroupID = valMap.Item("CurrentZoneGroupID"); CurrentZonePlayerUUIDsInGroup = valMap.Item("CurrentZonePlayerUUIDsInGroup") }) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} | |
member __.GetZoneGroupState() = | |
async { | |
let vals = [] | |
let! resValMapOrEx = __.DoAction("GetZoneGroupState", vals) | |
match resValMapOrEx with | |
| Choice1Of2(valMap) -> return Choice1Of2({ ZoneGroupStateResponse.ZoneGroupState = valMap.Item("ZoneGroupState") }) | |
| Choice2Of2(ex) -> return Choice2Of2(ex) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You'll note that the properties for this service are quite stringy. Wont be like that for long.