Cannot use AFNetworking to upload image - afnetworking

I am creating an iOS app using Rubymotion. I am trying to make a multipart upload
of an image.
I use this code to make upload but I get error:
data = {token: "2xCGdzcuEeNzhst3Yaa8f", task: 1, message: "message", latitude: 1, longitude: 1}
client = AFHTTPClient.alloc.initWithBaseURL(NSURL.URLWithString("http://api.example.com/api/v1/"))
request = client.multipartFormRequestWithMethod('POST', path:"messages", parameters:data, constructingBodyWithBlock:lambda{ |form_data|
image_data = UIImagePNGRepresentation(image.image)
form_data.appendPartWithFileData(image_data, name:'new_avatar', fileName:'new_avatar.png', mimeType:'image/png')
})
operation = AFJSONRequestOperation.alloc.initWithRequest(request)
operation.setCompletionBlockWithSuccess(lambda{ |operation, responseObject| puts 'all done!'})
I get this error:
undefined method `setCompletionBlockWithSuccess' for #<AFJSONRequestOperation:0xb227f00> (NoMethodError)
From what I can see, operation is a valid object and should have this method.
Am I missing something here?
Update 1
This is my updated code but when I run it the POST action does not seem to fire. Am I still missing any code? I do not get any errors either.
data = {token: "2xCGdzcuEeNzhs5tYaa8f", task: 1, message: "message", latitude: 1, longitude: 1}
client = AFHTTPClient.alloc.initWithBaseURL(NSURL.URLWithString("http://api.example.com/api/v1/"))
request = client.multipartFormRequestWithMethod('POST', path:"messages", parameters:data, constructingBodyWithBlock:lambda{ |form_data|
image_data = UIImagePNGRepresentation(image.image)
form_data.appendPartWithFileData(image_data, name:'new_avatar', fileName:'new_avatar.png', mimeType:'image/png')
})
operation = AFJSONRequestOperation.alloc.initWithRequest(request)
operation.setCompletionBlockWithSuccess(lambda { |operation, responseObject| puts 'all done!'},
failure: lambda { |operation, error| puts 'error' })
The request object outputs this:
<NSMutableURLRequest:195641792 - url: http://api.example.com/api/v1/messages,
headers: {"Content-Length"=>"118200", "Content-Type"=>"multipart/form-data; boundary=Boundary+0xAbCdEfGbOuNdArY", "Accept-Language"=>"en, fr, de, ja, nl, it, es, pt, pt-PT, da, fi, nb, sv, ko, zh-Hans, zh-Hant, ru, pl, tr, uk, ar, hr, cs, el, he, ro, sk, th, id, ms, en-GB, ca, hu, vi, en-us;q=0.8", "User-Agent"=>"theapp/1.0 (iPhone Simulator; iOS 6.0; Scale/1.00)"},
cache policy: 0, Pipelining: false, main doc url: , timeout: 60.0, network service type: 0 >
The operation object outputs this:
<AFJSONRequestOperation:0xa78c660>

The method signature is setCompletionBlockWithSuccess(lambda..., failure: lambda...) -- you need to add a failure parameter. Something like this:
operation.setCompletionBlockWithSuccess(lambda { |operation, responseObject| puts 'all done!'},
failure: lambda { |operation, error| puts 'error' })
Also, you'll want to make sure to actually start the request operation:
operation.start
See https://github.com/AFNetworking/AFNetworking/blob/master/AFNetworking/AFJSONRequestOperation.m#L102-L103 for the definition of this method.

I wrote a class to do this kind of work. Check out my answer HERE. It uses AFNetworking and includes methods for basic network requests.

Related

Ejabberd - Run SQL Query for Custom Command

I'm trying to make a custom command in mod_admin_extra.erl. to fetch messages between 2 JIDs.
My command will look like this:-
ejabberdctl get_messages HOST FROM TO START_TIME END_TIME
The SQL query will be like:-
select * from archive where (username = FROM and bare_peer = TO) OR (username=TO and bare_peer = FROM) where created_at BETWEEN START_TIME AND END_TIME;
I went through this thread to understand how IQ query works and want to build a similar sort of a thing via the command and API.
How do I fire the query in the above function so as to fetch the messages between the conversations of 2 JIDs??
My response would be a list of dictionaries:-
[{from: jid1, to: jid2, body: Hello, created_at: T1}]
I would be in turn using the same command for the POST API to fetch messages.
UPDATE
As per the suggestion provided by #Badlop, I updated my function with
% ----------------- Custom Command Get Message ----------------------
#ejabberd_commands{name = get_message, tags = [stanza],
desc = "Get messages from a local or remote bare of full JID",
longdesc = "Get messages of a specific JID sent to a JID",
module = ?MODULE, function = get_message,
args = [{host, binary}, {from, binary}, {to, binary},
{start_time, binary}, {end_time, binary}],
args_example = [<<"localhost">>, <<"admin">>, <<"user1">>,
<<"2015-07-00T00:00:00Z">>, <<"2015-07-029T13:23:54Z">>],
args_desc = ["Host", "From JID", "Receiver JID", "Start Time", "End Time"],
result = {result, {
tuple, [{messages, list, {message, {tuple,
[
{timestamp, string},
{xml, string},
{txt, string},
{peer, integer},
{kind, integer},
{nick, string}
]}}},
{status, string},
{count, integer}]}}
},
% ----------------- Custom Command Ends -----------------------------
This is my function that gets called when the command is received.
% ----------------- Custom Function Get Message ----------------------
get_message(Host, From, To, StartTime, EndTime) ->
mod_mam:select(
Host,
jid:make(From, Host),
jid:make(From, Host),
[{start, xmpp_util:decode_timestamp(StartTime)},
{'end', xmpp_util:decode_timestamp(EndTime)},
{with, jid:make(To, Host)}],
#rsm_set{},
chat,
all
).
% ----------------- Custom Function Get Message ----------------------
However, it returns an error response:-
Unhandled exception occurred executing the command:
** exception error: no function clause matching
ejabberd_ctl:format_result([],
{messages,list,
{message,
{tuple,
[{timestamp,string},
{xml,string},
{peer,integer},
{kind,integer},
{nick,string}]}}}) (src/ejabberd_ctl.erl, line 405)
in function ejabberd_ctl:format_result/2 (src/ejabberd_ctl.erl, line 461)
in call from ejabberd_ctl:try_call_command/4 (src/ejabberd_ctl.erl, line 321)
in call from ejabberd_ctl:process2/4 (src/ejabberd_ctl.erl, line 274)
in call from ejabberd_ctl:process/2 (src/ejabberd_ctl.erl, line 252)
in call from rpc:'-handle_call_call/6-fun-0-'/5 (rpc.erl, line 197)
The query printed in the logs in as follow:-
2020-04-24 21:57:13.717746+05:30 [debug] SQL: "SELECT timestamp, xml, peer, kind, nick FROM archive WHERE username=E'admin' and server_host=E'localhost' and bare_peer=E'test#localhost' and timestamp >= 1587692943312536 and timestamp <= 1587779343312536 ORDER BY timestamp ASC ;"
2020-04-24 21:57:13.726745+05:30 [debug] SQL: "SELECT COUNT(*) FROM archive WHERE username=E'admin' and server_host=E'localhost' and bare_peer=E'test#localhost' and timestamp >= 1587692943312536 and timestamp <= 1587779343312536;"
This is database independent:
mod_mam:select(
<<"localhost">>,
jid:make(<<"user1">>, <<"localhost">>),
jid:make(<<"user1">>, <<"localhost">>),
[{start, xmpp_util:decode_timestamp(<<"2020-04-24T14:37:25Z">>)},
{'end', xmpp_util:decode_timestamp(<<"2020-04-24T14:37:30Z">>)},
{with, jid:make(<<"user2">>,<<"localhost">>)}],
#rsm_set{},
chat,
all
).
Umm, you were still far away, the command result was wrong, and the call result must be processed. what about this?
$ ejabberdctl get_mam_messages user1#localhost user2#localhost 2020-04-27T00:00:00Z 2020-04-27T23:59:59Z
Required patch:
diff --git a/src/mod_mam.erl b/src/mod_mam.erl
index 08a4059b4..d2d74913c 100644
--- a/src/mod_mam.erl
+++ b/src/mod_mam.erl
## -42,6 +42,7 ##
get_room_config/4, set_room_option/3, offline_message/1, export/1,
mod_options/1, remove_mam_for_user_with_peer/3, remove_mam_for_user/2,
is_empty_for_user/2, is_empty_for_room/3, check_create_room/4,
+ get_messages_command/4,
process_iq/3, store_mam_message/7, make_id/0, wrap_as_mucsub/2, select/7]).
-include("xmpp.hrl").
## -1355,8 +1356,29 ## get_jids(undefined) ->
get_jids(Js) ->
[jid:tolower(jid:remove_resource(J)) || J <- Js].
+get_messages_command(From, To, StartTime, EndTime) ->
+ FromJid = jid:decode(From),
+ {Stanzas, _, _} =
+ mod_mam:select(
+ FromJid#jid.lserver, FromJid, FromJid,
+ [{start, xmpp_util:decode_timestamp(StartTime)},
+ {'end', xmpp_util:decode_timestamp(EndTime)},
+ {with, jid:decode(To)}],
+ #rsm_set{}, chat, all),
+ [fxml:element_to_binary(xmpp:encode(Subels))
+ || {_, _, #forwarded{sub_els = [Subels]}} <- Stanzas].
+
get_commands_spec() ->
- [#ejabberd_commands{name = delete_old_mam_messages, tags = [purge],
+ [#ejabberd_commands{
+ name = get_mam_messages, tags = [mam],
+ desc = "Get archived messages of an account with another contact",
+ module = ?MODULE, function = get_messages_command,
+ args = [{from, binary}, {to, binary}, {start, binary}, {'end', binary}],
+ args_example = [<<"user1#localhost">>, <<"user2#example.org">>,
+ <<"2020-04-27T00:00:00Z">>, <<"2020-04-27T23:59:59Z">>],
+ args_desc = ["Local JID", "Contact JID", "Start Time", "End Time"],
+ result = {messages, {list, {message, string}}}},
+ #ejabberd_commands{name = delete_old_mam_messages, tags = [purge],
desc = "Delete MAM messages older than DAYS",
longdesc = "Valid message TYPEs: "
"\"chat\", \"groupchat\", \"all\".",

Elixir marshal ISO 8583 message error with Erlang library

I am new to elixir and I need to create ISO 8583 client with this language and Phoenix framework. I found an Erlang library for it from stackoverflow thread here, compiled successfully and followed the example in the repository here but got error when marshaling the message. Here is my Elixir code to marshal the message:
msg1 = :erl8583_message.new()
msg2 = :erl8583_message.set_mti("0800", msg1)
msg3 = :erl8583_message.set(3, "300000", msg2)
msg4 = :erl8583_message.set(24, "045", msg3)
msg5 = :erl8583_message.set(41, "11111111", msg4)
msg6 = :erl8583_message.set(42, "222222222222222", msg5)
msg7 = :erl8583_message.set(63, "This is a Test Message", msg6)
marshalled = :erl8583_marshaller_ascii.marshal(msg7)
That's just an elixir version from the example on the repo. This is the error I've got when running the app:
[error] #PID<0.438.0> running TestlangIsoClientWeb.Endpoint (cowboy_protocol) terminated
Server: 127.0.0.1:4001 (http)
Request: POST /api/process
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in :erl8583_marshaller_ascii.marshal_data_element/2
(erl8583) /home/muhammad/Workspace/testlang/testlang_iso_client/deps/erl8583/src/erl8583_marshaller_ascii.erl:168: :erl8583_marshaller_ascii.marshal_data_element({:n, :fixed, 4}, "0800")
(erl8583) /home/muhammad/Workspace/testlang/testlang_iso_client/deps/erl8583/src/erl8583_marshaller.erl:108: :erl8583_marshaller.marshal/2
(testlang_iso_client) lib/testlang_iso_client_web/controllers/my_controller.ex:61: TestlangIsoClientWeb.MyController.process/2
(testlang_iso_client) lib/testlang_iso_client_web/controllers/my_controller.ex:1: TestlangIsoClientWeb.MyController.action/2
(testlang_iso_client) lib/testlang_iso_client_web/controllers/my_controller.ex:1: TestlangIsoClientWeb.MyController.phoenix_controller_pipeline/2
(testlang_iso_client) lib/testlang_iso_client_web/endpoint.ex:1: TestlangIsoClientWeb.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
(testlang_iso_client) lib/testlang_iso_client_web/endpoint.ex:1: TestlangIsoClientWeb.Endpoint.plug_builder_call/2
(testlang_iso_client) lib/testlang_iso_client_web/endpoint.ex:1: TestlangIsoClientWeb.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /home/muhammad/Workspace/testlang/testlang_iso_client/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
Is there something I missed to make it work? Any help would be very appreciated.
Updated
I have tried to changed the string parameter to charlist, but still got the same error. Here is the code snippet:
def test(conn, _params) do
IO.puts("Test")
msg1 = :erl8583_message.new()
msg2 = :erl8583_message.set_mti('0800', msg1)
msg3 = :erl8583_message.set(3, '300000', msg2)
msg4 = :erl8583_message.set(24, '045', msg3)
msg5 = :erl8583_message.set(41, '11111111', msg4)
msg6 = :erl8583_message.set(42, '222222222222222', msg5)
msg7 = :erl8583_message.set(63, 'This is a Test Message', msg6)
marshalled = :erl8583_marshaller_ascii.marshal(msg7)
json(conn, %{status: "ok"})
end
Here is the function erl8583_marshaller.erl:108 mentioned in the stacktrace:
marshal(Message, MarshalHandlers) ->
OptionsRecord = parse_options(MarshalHandlers, #marshal_options{}),
{Marshalled1, Message1} = init_marshalling(OptionsRecord, Message),
MarshalledMti = encode_mti(OptionsRecord, Message1), % --- Line 108
Marshalled2 = <<Marshalled1/binary, MarshalledMti/binary>>,
{MarshalledBitmap, Message2} = encode_bitmap(OptionsRecord, Message1),
Marshalled3 = <<Marshalled2/binary, MarshalledBitmap/binary>>,
MarshalledFields = encode_fields(OptionsRecord, Message2),
Marshalled4 = <<Marshalled3/binary, MarshalledFields/binary>>,
end_marshalling(OptionsRecord, Message2, Marshalled4).
And here is the function erl8583_marshaller_ascii.erl:168 mentioned in the stacktrace:
%%
%% Local Functions
%%
marshal_data_element({n, llvar, Length}, FieldValue) when length(FieldValue) =< Length ->
erl8583_convert:integer_to_string(length(FieldValue), 2) ++ FieldValue;
I don't understand why the call to that function was failed to match with parameters {:n, :fixed, 4}, "0800" that was sent from my function. I have tried to change the double quotes to single quotes with no success. Is there any other suggestions what am I supposed to do?
there may be a bug in the code.
you can reference this issue here
there is one elixir library out which is relatively new.
its called ale8583.
documentation is still coming out on this one but looks very promising.
you can check it out.
Try passing charlists instead of strings:
msg1 = :erl8583_message.new()
msg2 = :erl8583_message.set_mti('0800', msg1)
msg3 = :erl8583_message.set(3, '300000', msg2)
msg4 = :erl8583_message.set(24, '045', msg3)
msg5 = :erl8583_message.set(41, '11111111', msg4)
msg6 = :erl8583_message.set(42, '222222222222222', msg5)
msg7 = :erl8583_message.set(63, 'This is a Test Message', msg6)
marshalled = :erl8583_marshaller_ascii.marshal(msg7)
There is potential for confusion here:
What Erlang calls "strings" and puts in double quotes ("foo"), Elixir calls "charlists" and puts in single quotes ('foo').
What Elixir calls "strings" and puts in double quotes ("foo"), Erlang calls "binaries" and puts in double quotes plus angle brackets (<<"foo">>).
It seems like the erl8583 library expects Erlang strings throughout.

Making a variable number of parallel HTTP requests with Gatling?

I am trying to model a server-to-server REST API interaction in Gatling 2.2.0. There are several interactions of the type "request a list and then request all items on the list at in parallel", but I can't seem to model this in Gatling. Code so far:
def groupBy(dimensions: Seq[String], metric: String) = {
http("group by")
.post(endpoint)
.body(...).asJSON
.check(
...
.saveAs("events")
)
}
scenario("Dashboard scenario")
.exec(groupBy(dimensions, metric)
.resources(
// a http() for each item in session("events"), plz
)
)
I have gotten as far as figuring out that parallel requests are performed by .resources(), but I don't understand how to generate a list of requests to feed it. Any input is appreciated.
Below approach is working for me. Seq of HttpRequestBuilder will be executed concurrently:
val numberOfParallelReq = 1000
val scn = scenario("Some scenario")
.exec(
http("first request")
.post(url)
.resources(parallelRequests: _*)
.body(StringBody(firstReqBody))
.check(status.is(200))
)
def parallelRequests: Seq[HttpRequestBuilder] =
(0 until numberOfParallelReq).map(i => generatePageRequest(i))
def generatePageRequest(id: Int): HttpRequestBuilder = {
val body = "Your request body here...."
http("page")
.post(url)
.body(StringBody(body))
.check(status.is(200))
}
Not very sure of your query but seems like you need to send parallel request which can be done by
setUp(scenorio.inject(atOnceUsers(NO_OF_USERS)));
Refer this http://gatling.io/docs/2.0.0-RC2/general/simulation_setup.html

HOW TO: call stored procedures with Tds Library in Elixir

I get the following error trying to call a stored procedure using the Tds library for Elixir
The stored procedure get_account exists and has exactly one parameter #id
iex(5)>Tds.Connection.query(pid, "get_account",[%Tds.Parameter{name: "#id", value: 1}])
{:error,
%Tds.Error{message: nil,
mssql: %{class: 16, length: 252, line_number: 0, msg_text: "Procedure or function 'get_account' expects parameter '#id', which was not supplied.", number: 201, proc_name: "get_account",
server_name: "localhost\\SQLEXPRESS", state: 4}}}
iex(6)>
Trying this with Tds.proc(pid, "get_account",[1]) does not work either
Workaround:
Tds.query(pid, "get_account 1",[])
Use this the same way you would pass parameters directly to a stored proc using EXEC.
Updated:
This format also works:
params = [
%Tds.Parameter{name: "#1", value: 100, type: :integer},
%Tds.Parameter{name: "#2", value: 100, type: :integer},
%Tds.Parameter{name: "#3", value: <<0 ,0 ,0 ,0>>, type: :binary},
]
Conn.query(s.db, "save_auth_key #1, #2, #3", params)

Lua Script Error

Situation:
I want to save the record of a data which is a value of the sensor in the certain file.
Code is..
--Header file
require("TIMER")
require("IPBOX")
require("ANALOG_IN")
require("LOG")
function OnExit()
print("Exit code...do something")
end
function main()
timer = "Timer"
local analogsensor_1 = "AIR_1"
local analogsensor_2 = "AIR_2"
local timestr = os.data("%Y-%m-%d %H:%M:%S")
-- open the file for writing binary data
local filehandle = io.open("collection_of_data.txt", "a")
while true do
valueOfSensor_1 = ANALOG_IN.readAnalogIn(analogsensor_1);
valueOfSensor_2 = ANALOG_IN.readAnalogIn(analogsensor_2);
if (valueOfSensor_1 > 0 and valueOfSensor_2 > 0) then
-- save values of sensors
filehandle:write(timestr, " -The Value of the Sensors: ", tostring(valueOfSensor_1), tostring(valueOfSensor_2)"\n");
-- save values using rolling log appender:
LOG.log_event( ScenarioLoggerDevicenameInDeviceList, " -The Value of the Sensors: ", tostring(valueOfSensor_1), tostring(valueOfSensor_2), "any other string you wish to add", "etc", "etc")
LOG.log_event( ScenarioLoggerDevicenameInDeviceList, " -The Value of the Sensors: ", tostring(valueOfSensor_1))
print("Hello3"..valueOfSensor_1)
end
TIMER.sleep(timer,500)
end
-- close the file
filehandle:close()
end
print("start main")
main()
In this line:
filehandle:write(timestr, " -The Value of the Sensors: ", tostring(valueOfSensor_1), tostring(valueOfSensor_2)"\n");
I get an error:
"attemp to index global 'filehandle' (a nil value)"
How can I fix it?
io.open returns nil if it cannot open the file. This can be due to "file not found", "permissions denied" and maybe other reasons. To figure out the problem, io.open has a second return value, which lets you inspect the error (in fact, it even returns a third value, which is an error-code integer - but its meaning is system dependent).
Change:
local filehandle = io.open("collection_of_data.txt", "a")
to
local filehandle, message = io.open("collection_of_data.txt", "a")
if not filehandle then
print(message)
end
You can also use the following Lua idiom:
local filehandle = assert(io.open("collection_of_data.txt", "a"))
This will do the same. If the first argument to assert is nil, then the second argument (the second return value of io.open will be printed. If the first argument is not nil, it will simply be returned.

Resources