-# Wampex
+# WAMPex
-**TODO: Add description**
+WAMPex is a client library for the [WAMP protocol](https://wamp-proto.org/index.html)
+
+This client library currently implements the [Basic Profile](https://wamp-proto.org/_static/gen/wamp_latest.html#basic-and-advanced-profiles)
+
+This means, currently, there is no authentication, but it is on the roadmap.
## Installation
-If [available in Hex](https://hex.pm/docs/publish), the package can be installed
-by adding `wampex` to your list of dependencies in `mix.exs`:
+Currently it's not available on hex.pm. I want to get a little more real-world testing done before committing to the implementation. However, it is available on Gitlab. You can add the following to your `mix.exs` file to use it.
```elixir
def deps do
[
- {:wampex, "~> 0.1.0"}
+ {:wampex,
+ git: "https://gitlab.com/entropealabs/wampex",
+ tag: "f998f7280ae671de08b391155d935ae370fa3cad"}
]
end
```
-Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
-and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
-be found at [https://hexdocs.pm/wampex](https://hexdocs.pm/wampex).
+## Documentation
+
+Docs are available at [HexDocs](https://hexdocs.pm/wampex)
+
+## Usage
+
+You can see a full example app, emulating a Smart Home and backend system [here](https://gitlab.com/entropealabs/wampex_example_app)
+
+Currently the only transport supported is WebSockets, but raw TCP is planned for the near future.
+
+WAMPex defaults to WebSocket as the transport and MessagePack as the serialization format.
+
+A simple [Session](https://wamp-proto.org/_static/gen/wamp_latest.html#sessions) can be configured like so.
+
+```elixir
+alias Wampex.{Realm, Session}
+alias Wampex.Role.{Callee, Caller, Publisher, Subscriber}
+
+url = "http://localhost:18080/ws"
+realm = %Realm{name: "com.myrealm"}
+
+roles = [Callee, Caller, Publisher, Subscriber]
+session = Session.new(url, realm, controller_roles)
+
+Wampex.start_link(name: Connection, session: session)
+```
+
+The name can be anything you want, it is required, and must be unique among multiple WAMPex instances. See the [example application](https://gitlab.com/entropealabs/wampex_example_app) for an example of running multiple connections/sessions.
+
+There are behaviours for transports and serializers if you wanted to write your own.
+
+You can override the default serializer and transport like this.
+
+```elixir
+alias Wampex.{Realm, Session}
+alias Wampex.Role.{Callee, Caller, Publisher, Subscriber}
+alias Wampex.Serializer.JSON
+alias Wampex.Transport.WebSocket
+
+url = "http://localhost:18080/ws"
+realm = %Realm{name: "com.myrealm"}
+
+roles = [Callee, Caller, Publisher, Subscriber]
+session = Session.new(url, realm, controller_roles, WebSocket, "wamp.2.json", JSON)
+
+Wampex.start_link(name: Connection, session: session)
+```
+
+The protocol uses a registered [WebSocket subprotocol](https://wamp-proto.org/_static/gen/wamp_latest.html#websocket-transport), there are several values available. You need to ensure that the [Router](https://wamp-proto.org/_static/gen/wamp_latest.html#peers-and-roles) that you connect to also supports the subprotocol.
+
+### Details
+
+WAMPex currently maps each session to a seperate transport connection. This means there is a new conection per instance of WAMPex.
+
+The Session management is handled by a state machine, written using [StatesLanguage](https://github.com/citybaseinc/states_language). The JSON looks like this.
+
+```json
+{
+ "Comment": "Session State Machine",
+ "StartAt": "WaitForTransport",
+ "States": {
+ "WaitForTransport": {
+ "Type": "Task",
+ "Resource": "InitTransport",
+ "TransitionEvent": "{:connected, true}",
+ "Next": "Init",
+ "Catch": [
+ {
+ "ErrorEquals": ["{:connected, false}"],
+ "Next": "Abort"
+ }
+ ]
+ },
+ "Init": {
+ "Type": "Task",
+ "Resource": "Hello",
+ "TransitionEvent": ":hello_sent",
+ "Next": "Established",
+ "Catch": [
+ {
+ "ErrorEquals": [":abort"],
+ "Next": "Abort"
+ }
+
+ ]
+ },
+ "Established": {
+ "Type": "Choice",
+ "Resource": "Established",
+ "Choices": [
+ {
+ "StringEquals": ":message_received",
+ "Next": "HandleMessage"
+ },
+ {
+ "StringEquals": ":goodbye",
+ "Next": "GoodBye"
+ },
+ {
+ "StringEquals": ":abort",
+ "Next": "Abort"
+ }
+ ]
+ },
+ "HandleMessage": {
+ "Type": "Choice",
+ "Resource": "HandleMessage",
+ "Choices": [
+ {
+ "StringEquals": ":noop",
+ "Next": "Established"
+ },
+ {
+ "StringEquals": ":event",
+ "Next": "Event"
+ },
+ {
+ "StringEquals": ":invocation",
+ "Next": "Invocation"
+ },
+ {
+ "StringEquals": ":abort",
+ "Next": "Abort"
+ },
+ {
+ "StringEquals": ":goodbye",
+ "Next": "GoodBye"
+ }
+ ]
+ },
+ "Event": {
+ "Type": "Task",
+ "Resource": "HandleEvent",
+ "Next": "Established"
+ },
+ "Invocation": {
+ "Type": "Task",
+ "Resource": "HandleInvocation",
+ "Next": "Established"
+ },
+ "GoodBye": {
+ "Type": "Task",
+ "Resource": "GoodBye",
+ "End": true
+ },
+ "Abort": {
+ "Type": "Task",
+ "Resource": "Abort",
+ "End": true
+ }
+ }
+}
+```
+You can copy and paste this snippet into the JSON input at https://citybaseinc.github.io/states-language-editor/ to edit and visualize the state machine.