I currently using rabbit_client to send queue message from our ejabberd. This message is triggered using ejabberd hook. Can successfully compiled and installed without any issue.
I keep on getting the same error when the try to create the connection. Appreciated if someone could give some clue on the issue.
Following is the code used to connect and publish the message.
{ok, Connection} =
amqp_connection:start(#amqp_params_network{host = "192.168.xx.xx", username = "username", password= "password"}),
{ok, Channel} = amqp_connection:open_channel(Connection),
amqp_channel:call(Channel, #'queue.declare'{queue = <<"hello">>}),
amqp_channel:cast(Channel,
#'basic.publish'{
exchange = <<"">>,
routing_key = <<"hello">>},
#amqp_msg{payload = <<"Hello World!">>}),
io:format(" [x] Sent 'Hello World!'~n"),
ok = amqp_channel:close(Channel),
ok = amqp_connection:close(Connection),
ok.
Error
{undef,[{amqp_connection,start,[{amqp_params_network,"username","password",<<"/">>,"192.168.xx.xx",undefined,0,0,10,infinity,none,[#Fun,#Fun],[],[]}],[]},{mod_mymod,send_internal_notice,4,[{file,"src/mod_mymod.erl"},{line,67}]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,329}]},{ejabberd_c2s,presence_update,3,[{file,"src/ejabberd_c2s.erl"},{line,2068}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1249}]},{p1_fsm,handle_msg,10,[{file,"src/p1_fsm.erl"},{line,582}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]}
{undef,[{amqp_connection,start,... means that the amqp_connection:start/1 function was not defined (undef). This usually means that the amqp_connection module isn't in the Erlang code path.
Related
I try to receive simple text values from external MQTT broker topics with IoT Gateway.
For this purpose I simplify the existing script (extensions/mqtt/custom_mqtt_uplink_converter.py):
from thingsboard_gateway.connectors.mqtt.mqtt_uplink_converter import MqttUplinkConverter, log
class CustomMqttUplinkConverter(MqttUplinkConverter):
def __init__(self, config):
self.__config = config.get('converter')
self.dict_result = {}
def convert(self, topic, body):
try:
log.debug("New data received: %s: %s" % (topic,body))
# if topic = '/devices/buzzer/controls/volume' device name will be 'buzzer'.
self.dict_result["deviceName"] = topic.split("/")[2]
# just hardcode this
self.dict_result["deviceType"] = "buzzer"
self.dict_result["telemetry"] = {"data": body}
log.debug("Result: %s" % (self.dict_result))
return self.dict_result
except ...
When I start gateway I see in his log that he successfully connected and read the values:
INFO ... MQTT Broker Connector connected to 10.1.1.2:1883 - successfully.'
DEBUG ... Client <paho.mqtt.client.Client object at 0x7fb42d19dd68>, userdata None, flags {'session present': 0}, extra_params ()'
DEBUG ... <module 'CustomMqttUplinkConverter' from '/var/lib/thingsboard_gateway/extensions/mqtt/custom_mqtt_uplink_converter.py'>'
DEBUG ... Import CustomMqttUplinkConverter from /var/lib/thingsboard_gateway/extensions/mqtt.'
DEBUG ... Converter CustomMqttUplinkConverter for topic /devices/buzzer/controls/volume - found!'
INFO ... Connector "MQTT Broker Connector" subscribe to /devices/buzzer/controls/volume'
DEBUG ... Received data: {}'
DEBUG ... (None,)'
INFO ... "MQTT Broker Connector" subscription success to topic /devices/buzzer/controls/volume, subscription message id = 1'
DEBUG ... New data received: /devices/buzzer/controls/volume: 66'
DEBUG ... Result: {'deviceName': 'buzzer', 'deviceType': 'buzzer', 'telemetry': {'data': 66}}'
But this values are the last values he can read. If I change volume one broker new values will not appear neither in the log nor in TB UI. (I control updates with mosquitto_sub.)
Seems this converter will never called again until gateway restarted. Is it correct behaveour?
How can I make sure that my code is correct if I don't see the result?
Hi I have tried your version of the custom converter, it didn't work, but when I changed
self.dict_result["telemetry"] = {"data": body}
to
self.dict_result["telemetry"] = [{"data": body}]
It sent data correctly.
The gateway requires an array of telemetry of attributes from the converter.
I'm a beginner on Erlang-Ejabberd development and i want to create a module on top of Ejabberd 15.07. So i got some code as example in many posts and some tutorials to start developing my own module. Now i came out with this code to get started.
-module(mod_test)
-behaviour(gen_mod).
-ifndef(LAGER).
-define(LAGER, 1).
-endif.
-define(NS_SEEN, <<"jabber:iq:seen">>).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("jlib.hrl").
-export([start/2, stop/1, process_sm_iq/3]).
start(Host, Opt) ->
?INFO_MSG(" mod_test starting ", []),
IQDisc = gen_mod:get_opt(iqdisc, Opt, fun gen_iq_handler:check_type/1, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_SEEN, ?MODULE, process_sm_iq, IQDisc),
ok.
stop(Host) ->
?INFO_MSG(" mod_test2 stopping ", []),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_SEEN),
ok.
process_sm_iq(_From, _To, #iq{type = get, xmlns = ?NS_SEEN} = IQ) ->
?INFO_MSG(" Processing IQ Get query:~n ~p ", [IQ]),
IQ#iq{type = result, sub_el = [{xmlelement, <<"value">>, [], [{xmlcdata, <<"Hello World of Testing. ">>}]}]}.
So here, using Strophe.js i send a custom IQ stanza with this function.
var iq = $iq( {type: 'get', id : 'id123', from : 'renato#localhost'}).c('query', {xmlns : 'jabber:iq:seen'});
connection.sendIQ(iq, onResult);
And it comes out with a Stanza like this.
<iq type="get" id="id123" from="renato#localhost" xmlns="jabber:client">
<query xmlns="jabber:iq:seen" >
</iq>
Then i get disconnected and get no result from the server as expected. This is what i got in the log file.
2016-05-11 17:47:28.965 [info]<0.486.0>#ejabberd_listener:accept:299 (#Port<0.3939>) Accepted connection 127.0.0.1:49120 -> 127.0.0.1:5280
2016-05-11 17:47:28.966 [info]<0.507.0>#ejabberd_http:init:157 started: {gen_tcp,#Port<0.3939>}
2016-05-11 17:47:29.511 [info]<0.509.0>#ejabberd_c2s:wait_for_sasl_response:932 ({socket_state,ejabberd_http_bind,{http_bind,<0.508.0>, {{127,0,0,1},49120}},ejabberd_http_bind}) Accepted authentication for renato by undefined from 127.0.0.1
2016-05-11 17:47:30.150 [info]<0.509.0>#ejabberd_c2s:wait_for_session:1120 ({socket_state,ejabberd_http_bind,{http_bind,<0.508.0>, {{127,0,0,1},49120}},ejabberd_http_bind}) Opened session for renato#localhost/32685205291462981649937971
2016-05-11 17:47:31.451 [info]<0.486.0>#ejabberd_listener:accept:299 (#Port<0.3948>) Accepted connection 127.0.0.1:49122 -> 127.0.0.1:5280
2016-05-11 17:47:31.452 [info]<0.511.0>#ejabberd_http:init:157 started: {gen_tcp,#Port<0.3948>}
2016-05-11 17:47:31.453 [info]<0.390.0>#mod_test2:process_sm_iq:45 Processing IQ Get query:
{iq,<<"id123">>,get,<<"jabber:iq:seen">>,<<>>,{xmlel,<<"query">>, [{<<"xmlns">>,<<"jabber:iq:seen">>},{<<"querytype">>,<<"seen">>}],[]}}
2016-05-11 17:49:01.556 [info]<0.508.0>#ejabberd_http_bind:handle_info:522 Session timeout. Closing the HTTP bind session: <<"1199a026fb06de7e7c728425587b09a0b9c81433">>
2016-05-11 17:49:01.556 [info]<0.509.0>#ejabberd_c2s:terminate:1842 ({socket_state,ejabberd_http_bind,{http_bind,<0.508.0>, {{127,0,0,1},49120}},ejabberd_http_bind}) Close session for renato#localhost/32685205291462981649937971
I'm running ejabberd 15.07. I installed the run package and compiled the module using these commands.
erlc -DNO_EXT_LIB -I lib/ejabberd-15.07/include -pz lib/ejabberd-15.07/lib mod_test.erl
After that, i copied the file to ebin/ directory then i started the ejabberd server and everything else worked fine. Someone can help me out and explain me what i have to, and show me if i have to change the code, configuration file or maybe use a newer version. I'm using this version for months. Thanks...
I want to convert an HTTP request to MQTT request. So for that I received the HTTP request which consist of the information like topic and message to publish. I have to publish the provided message to provided topic.
I am able to publish the message but the problem is that I can only provide the Topic and Payload to the function I used. Here is the piece of code I write to publish:
Data = mochiweb_request:parse_post(Req),
{RegisterFun, PublishFun, SubscribeFun} = vmq_reg:direct_plugin_exports(http_to_mqtt),
Topic = get_value("topic", Data),
List_of_topics = string:tokens(Topic, "/"),
Lot = lists:map(fun(X) -> list_to_binary(X) end, List_of_topics),
Payload = list_to_binary(get_value("message", Data)),
error_logger:info_msg("Topics: ~p~nPayload: ~p",[Lot, Payload]),
PublishFun(Lot,Payload),
Req:ok({"text/html", [], "<p>Thank you. <p>"})
Here the PublishFun I get from the vmq_reg can only allow to give topic and message. Is there any other way I can publish a message giving the value to Qos, Retain and Dup also.
I am creating a server using mochiweb and use it as a plugin in vernemq.
It is now possible in the new release of VerneMQ as stated by Andre.
Here is how it works :
Data = mochiweb_request:parse_post(Req),
{RegisterFun,PublishFun,SubscribeFun} = vmq_reg:direct_plugin_exports(http_to_mqtt),
Topic = get_value("topic", Data),
List_of_topics = string:tokens(Topic, "/"),
Lot = lists:map(fun(X) -> list_to_binary(X) end, List_of_topics),
Payload = list_to_binary(get_value("message", Data)),
Qos = erlang:list_to_integer(get_value("qos",Data)),
Retain = erlang:list_to_integer(get_value("retain",Data)),
error_logger:info_msg("Topics: ~p~nPayload: ~p~nQOS: ~p~nRetain: ~p",[Lot, Payload,Qos,Retain]),
PublishFun(Lot,Payload,#{qos => Qos, retain => Retain}),
Req:ok({"text/html", [], "<p>Thank you. <p>"})
It is not possible in the current version, but a planned feature for the future.
I have written a C# .net executable that sends an email through an outlook exchange server. Everything works fine when I run it manually, but when I use a scheduled task to call the executable it doesn't send the email. Everything else works fine, but the email doesn't get sent. I set the scheduled task to run as my user account. When the task is running I can see in Task Manager that the executable is running under my username. This rules out any obvious permissions issues.
While debugging I made the program output some text to a file on a network share on the same machine on which Exchange is running. This file outputs fine, so I know that the program can connect to that machine.
Can anyone help?
Ok, as you can see above I was trying to send mail through a running instance of Outlook. Although I wasn't able to post code without in a comment box without pulling my hair out #amitapollo gave me the clue to use the System.Net.Mail namespace. At the end of the day I got it to work. Here's my code:
System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient("myExchangeServerIPAddress");
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new System.Net.NetworkCredential("myDomain\\myUsername", "myPassword");
smtpClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
smtpClient.EnableSsl = true;
System.Security.Cryptography.X509Certificates.X509Store xStore = new System.Security.Cryptography.X509Certificates.X509Store();
System.Security.Cryptography.X509Certificates.OpenFlags xFlag = System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly;
xStore.Open(xFlag);
System.Security.Cryptography.X509Certificates.X509Certificate2Collection xCertCollection = xStore.Certificates;
System.Security.Cryptography.X509Certificates.X509Certificate xCert = new System.Security.Cryptography.X509Certificates.X509Certificate();
foreach (System.Security.Cryptography.X509Certificates.X509Certificate _Cert in xCertCollection)
{
if (_Cert.Subject.Contains("myUsername#myDomain.com"))
{
xCert = _Cert;
}
}
smtpClient.ClientCertificates.Add(xCert);
//I was having problems with the remote certificate no being validated so I had to override all security settings with this line of code...
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object s, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; };
smtpClient.Send("myUsername#myDomain.com", "myUsername#myDomain.com", "mySubject", "myBody");
I have a working Ejabberd server (version 2.1.9) and my client application running just fine, but I wish to modify the way the application's XMPP client connects to Ejabberd in order to reduce the number of requests/responses between them, because its for a mobile environment and I wish to reduce the initial connection time.
I've looked up the XMPP protocol specification (RFC 6120) and some protocol extensions (XEPs), namely XEP-0305 Quickstart, but the protocol itself doesn't specify single request sign in and the Quickstart extension although aims to reduce the number of requests isn't enough for the time reduction I'm looking for.
After searching and not finding any solution I've started to modify both client and server and wish to accomplish the following for now as a proof of concept:
//Client Request
<?xml version='1.0'?>
<stream:stream ... user='user' pass='pass'>
//Server Response
<?xml version='1.0'?>
<stream:stream ... success='1'>
I've managed to modify my client accordingly and the Ejabberd server, and it seems they connect successfully, but any request the client makes after establishing the session doesn't get a response by the server. I've used Wireshark to check the TCP connection client and server side: client side its open and the request is sent, and on the server side is also open and the request is received, but when I try to send the response it is not sent.
I've modified ONLY the file ejabberd_c2s.erl and the changes are the following:
//init function
...
%% changed the first state of the fsm to point to quickstart
%% {ok, wait_for_stream, #state{socket = Socket1,
{ok, wait_for_quickstart, #state{socket = Socket1,
...
//wait_for_quickstart function
...
case resource_conflict_action(U, StateData#state.server, R) of
closenew ->
send_header(StateData, Server, "1.0", DefaultLang, "0"),
send_trailer(StateData),
{stop, normal, StateData};
{accept_resource, R2} ->
JID = jlib:make_jid(U, StateData#state.server, R2),
allow = acl:match_rule(Server,c2s,JID),
case ejabberd_auth:check_password(U, Server, P) of
true ->
send_header(StateData, Server, "1.0", DefaultLang, "1"),
change_shaper(StateData, JID),
{Fs, Ts} = ejabberd_hooks:run_fold(
roster_get_subscription_lists,
StateData#state.server,
{[], []},
[U, StateData#state.server]),
LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)),
Fs1 = [LJID | Fs],
Ts1 = [LJID | Ts],
PrivList =
ejabberd_hooks:run_fold(
privacy_get_user_list,
StateData#state.server,
#userlist{},
[U, StateData#state.server]),
SID = {now(), self()},
Conn = get_conn_type(StateData),
Info = [{ip, StateData#state.ip},
{conn, Conn},
{auth_module, StateData#state.auth_module}],
ejabberd_sm:open_session(SID, U, StateData#state.server, R, Info),
NewStateData =
StateData#state{
user = U,
resource = R2,
jid = JID,
sid = SID,
conn = Conn,
auth_module = ejabberd_auth_internal,
authenticated = true,
pres_f = ?SETS:from_list(Fs1),
pres_t = ?SETS:from_list(Ts1),
privacy_list = PrivList},
fsm_next_state_pack(session_established,
NewStateData);
_ ->
%%auth fail
end
end.
Just to clarify: the initial client authentication request and server response are being transmitted just fine, subsequent requests are also being transmitted but there is no response to them.
I'm I overlooking something?
Thanks in advance
#Nuno-Freitas Indeed that was what was failing, thanks for your helpful insight.
I added the code:
R1 = xml:get_attr_s("r",Attrs),
R = case jlib:resourceprep(R1) of
error -> error;
"" ->
lists:concat([randoms:get_string() | tuple_to_list(now())]);
Resource -> Resource
end,
That made the server respond to my requests, but there was other thing amiss: the <presence/> tag was breaking on server because the #state.lang was not defined, so I had to define it in the wait_for_quickstart function and now I have a single sign in XMPP client server working proof of concept.