diff --git a/config/dev.sample.exs b/config/dev.sample.exs index 62648bb..9d9052b 100644 --- a/config/dev.sample.exs +++ b/config/dev.sample.exs @@ -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", diff --git a/lib/at_ex/gateway/Iot/publish_data.ex b/lib/at_ex/gateway/Iot/publish_data.ex new file mode 100644 index 0000000..c958dcd --- /dev/null +++ b/lib/at_ex/gateway/Iot/publish_data.ex @@ -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 // + - `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 diff --git a/lib/at_ex/iot.ex b/lib/at_ex/iot.ex new file mode 100644 index 0000000..13d502a --- /dev/null +++ b/lib/at_ex/iot.ex @@ -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 // + - `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 diff --git a/test/at_ex/gateway/Iot/publish_data_test.exs b/test/at_ex/gateway/Iot/publish_data_test.exs new file mode 100644 index 0000000..f3cc6fc --- /dev/null +++ b/test/at_ex/gateway/Iot/publish_data_test.exs @@ -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