Skip to content

Commit

Permalink
Merge pull request #79 from beamkenya/feature/IOT
Browse files Browse the repository at this point in the history
Started with IOT endpoint Functionality
  • Loading branch information
kamalogudah authored Aug 8, 2020
2 parents 589de0e + 70216bf commit 215cb88
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 1 deletion.
1 change: 0 additions & 1 deletion config/dev.sample.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ config :at_ex,
api_key: "===INSERT AFRICAS_TALKING_API_KEY HERE ===",
content_type: "application/x-www-form-urlencoded",
accept: "application/json",
auth_token: "",
username: "sandbox",
stk_product_name: "AtEx",
b2c_product_name: "AtEx",
Expand Down
49 changes: 49 additions & 0 deletions lib/at_ex/gateway/Iot/publish_data.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule AtEx.Gateway.Iot.PublishData do
import AtEx.Util

@moduledoc """
This module allows you to make an HTTP POST to publish messages to your remote devices.
"""
@live_url "https://iot.africastalking.com"
@sandbox_url "https://iot.africastalking.com"

use AtEx.Gateway.Base, url: get_url(@live_url, @sandbox_url), type: "json"

@doc """
This function makes a POST request to to publish messages to your remote devices through the
Africa's talking IOT endpoint
The function accepts a map of parameters.
## Parameters
attrs: - a map containing:
- `deviceGroup` - The device group to which the message is to be sent
- `topic` - The messaging channel to which the message is to be sent. In the form <username>/<device-group>/<the-topic>
- `payload` - The message packet to be sent to the subscribed devices.
## Example
iex> AtEx.Gateway.Iot.PublishData.publish(%{
...> deviceGroup: "CrazyCats",
...> topic: "any-topic",
...> payload: "take me to your leader"
...> })
{:ok, %{ "status" => true, "description" => "Message processed successfully"}}
"""

def publish(attrs) do
username = Application.get_env(:at_ex, :username)
device_group = attrs.deviceGroup
message_topic = attrs.topic
topic = "#{username}" <> "/" <> "#{device_group}" <> "/" <> "#{message_topic}"

params =
attrs
|> Map.put(:username, username)
|> Map.put(:topic, topic)

"/data/publish"
|> post(params)
|> process_result()
end
end
30 changes: 30 additions & 0 deletions lib/at_ex/iot.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule AtEx.IoT do
@moduledoc """
This module holds the implementation for the HTTP Gateway that runs calls against the Africas Talking API IoT endpoints
"""

alias AtEx.Gateway.Iot

@doc """
This function makes a POST request to to publish messages to your remote devices through the
Africa's talking IOT endpoint
The function accepts a map of parameters.
## Parameters
attrs: - a map containing:
- `deviceGroup` - The device group to which the message is to be sent
- `topic` - The messaging channel to which the message is to be sent. In the form <username>/<device-group>/<the-topic>
- `payload` - The message packet to be sent to the subscribed devices.
## Example
iex> AtEx.IoT.publish(%{
...> deviceGroup: "CrazyCats",
...> topic: "any-topic",
...> payload: "take me to your leader"
...> })
{:ok, %{ "status" => true, "description" => "Message processed successfully"}}
"""
defdelegate publish(map), to: Iot.PublishData
end
67 changes: 67 additions & 0 deletions test/at_ex/gateway/Iot/publish_data_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
defmodule AtEx.Gateway.Iot.PublishDataTest do
use ExUnit.Case
doctest AtEx.Gateway.Airtime
alias AtEx.Gateway.Iot.PublishData

setup do
Tesla.Mock.mock(fn
%{method: :post} ->
%Tesla.Env{
status: 201,
body:
Jason.encode!(%{"description" => "Message processed successfully", "status" => true})
}
end)

:ok
end

describe "IOT Publish data" do
test "publish/1 should publish data to a device" do
# make message details
publish_details = %{
deviceGroup: "CrazyCats",
topic: "any-topic",
payload: "take me to your leader"
}

# run details through our code
{:ok, result} = PublishData.publish(publish_details)

# assert our code gives us a single element list of messages
msg = result["description"]

# assert that message details correspond to details of set up message
assert msg == "Message processed successfully"
end
end

describe "fails" do
setup do
Tesla.Mock.mock(fn
%{method: :post} ->
%Tesla.Env{
status: 400,
body:
"The request content was malformed:\nObject is missing required member 'payload'"
}
end)

:ok
end

test "publish/1 should error out if payload is missing" do
# make message details
publish_details = %{deviceGroup: "CrazyCats", topic: "any-topic"}

# run details through our code
{:error, result} = PublishData.publish(publish_details)

assert result.status == 400

# assert that message details correspond to details of set up message
assert result.message ==
"The request content was malformed:\nObject is missing required member 'payload'"
end
end
end

0 comments on commit 215cb88

Please sign in to comment.