Skip to content

Instantly share code, notes, and snippets.

@bentayloruk
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bentayloruk/7392b1659903d540163f to your computer and use it in GitHub Desktop.
Save bentayloruk/7392b1659903d540163f to your computer and use it in GitHub Desktop.
One of many Sonos services in the F# type system
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)
}
@bentayloruk
Copy link
Author

You'll note that the properties for this service are quite stringy. Wont be like that for long.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment