How to enter an option during voice calls using at commands - command

I've been using a sim900 module to replicate many of the functions found in a basic cellphones for an embedded project. I've been successful with most functions with the exception of entering options during a voice call. I am actually looking for a generic solution (e.g. GSM 07.07 etc.) although the GSM/GPRS Module I'm using is the sim900.
Scenario: I initiate a call using ATD<number>; ,then automated voice asks me to dial "1" for an option. How do I send the "1"?
I've search high and low for an answer. I've been through the AT command manual over and over again. Please help.

Very good start in using the official GSM specification, although I want to note that 07.07 has been superseded by 27.007 a very long time ago, and you should use that document (or 27.005 if relevant).
I initially expected there to be two ways of achieving this, dial string modifiers or DTMF command, but I looking up the dial string in the 27.007 specification I do not find the p (pause) modifier1 I was expecting, and nearest thing, the W (wait) modifier is ignored and only included for compatibility.
Sending 0 through 9, A through D, * and # during a call is done using DTMF, although in a GSM network this is signalled separately out of band rather than sending in-band analogue tones. There is a specific command for sending DTMF tones called AT+VTS (with a horrible syntax). So that command is the answer to you question. Invoke it either from online command mode or from another serial connection.
1 The reason I was expecting a p modifier to exist is that I am able to enter one in phone book entries, e.g. `"12345678p123" which will dial 12345678, wait for the connection to be established and then send 123 as DTMF tones. But this is then obviously something (only) the user interface voice call handler manages and not the AT command handler.

Related

DPDK forward received packets to default network stack

We're using DPDK (version 20.08 on ubuntu 20.04, c++ application) to receive UDP packets with a high throughput (>2 Mpps). We use a Mellanox ConnectX-5 NIC (and a Mellanox ConnectX-3 in an older system, would be great if the solution worked there aswell).
Contrary, since we only need to send a few configuration messages, we send messages through the default network stack. This way, we can use lots of readily available tools to send configuration messages; however, since all the received data is consumed by DPDK, these tools do not get back any messages.
The most prominent issue arises with ARP negotiation: the host tries to resolve addresses, the clients also do respond properly, however, these responses are all consumed by DPDK such that the host cannot resolve the addresses and refuses to send the actual UDP packets.
Our idea would be to filter out the high throughput packets on our application and somehow "forward" everything else (e.g. ARP responses) to the default network stack. Does DPDK have a built-in solution for that? I unfortunatelly coulnd't find anything in the examples.
I've recently heard about the packet function which allows to inject packets into SOCK_DGRAM sockets which may be a possible solution. I also couldn't find a sample implementation for our use-case, though. Any help is greatly appreciated.
Theoretically, if the NIC in question supports the embedded switch feature, it should be possible to intercept the packets of interest in the hardware and redirect them to a virtual function (VF) associated with the physical function (PF), with the PF itself receiving everything else.
The user configures SR-IOV feature on the NIC / host as well as virtualisation support;
For a given NIC PF, the user adds a VF and binds it to the corresponding Linux driver;
The DPDK application is run with the PF ethdev and a representor ethdev for the VF;
To handle the packets in question, the application adds the corresponding flow rules.
The PF (ethdev 0) and the VF representor (ethdev 1) have to be explicitly specified by the corresponding EAL argument in the application: -a [pci:dbdf],representor=vf0.
As for the flow rules, there should be a pair of such.
The first rule's components are as follows:
Attribute transfer (demands that matching packets be handled in the embedded switch);
Pattern item REPRESENTED_PORT with port_id = 0 (instructs the NIC to intercept packets coming to the embedded switch from the network port represented by the PF ethdev);
Pattern items matching on network headers (these provide narrower match criteria);
Action REPRESENTED_PORT with port_id = 1 (redirects packets to the VF).
In the second rule, item REPRESENTED_PORT has port_id = 1, and action REPRESENTED_PORT has port_id = 0 (that is, this rule is inverse). Everything else should remain the same.
It is important to note that some drivers do not support item REPRESENTED_PORT at the moment. Instead, they expect that the rules be added via the corresponding ethdevs. This way, for the provided example: the first rule goes to ethdev 0, the second one goes to ethdev 1.
As per the OP update, the adapter in question might indeed support the embedded switch feature. However, as noted above, item REPRESENTED_PORT might not be supported. The rules should be inserted via specific ethdevs. Also, one more attribute, ingress, might need to be specified.
In order to check whether this scheme works, one should be able to deploy a VF (as described above) and run testpmd with the aforementioned EAL argument. In the command line of the application, the two flow rules can be tested as follows:
flow create 0 ingress transfer pattern eth type is 0x0806 / end actions represented_port ethdev_port_id 1 / end
flow create 1 ingress transfer pattern eth type is 0x0806 / end actions represented_port ethdev_port_id 0 / end
Once done, that should pass ARP packets to the VF (thus, to the network interface) in question. The rest of packets should be seen by testpmd in active forwarding mode (start command).
NOTE: it is recommended to switch to the most recent DPDK release.
For the current use case, the best option is to make use of DPDK TAP PMD (which is part of LINUX DPDK). You can use Software or Hardware to filter the specific packets then sent it desired TAP interface.
A simple example to demonstrate the same would be making use DPDK skeleton example.
build the DPDK example via cd [root folder]/example/skeleton; make static
pass the desired Physical DPDK PMD NIC using DPDK eal options ./build/basicfwd -l 1 -w [pcie id of DPDK NIC] --vdev=net_tap0;iface=dpdkTap
In second terminal execute ifconfig dpdkTap 0.0.0.0 promisc up
Use tpcudmp to capture Ingress and Egress packets using tcpdump -eni dpdkTap -Q in and tcpdump -enu dpdkTap -Q out respectively.
Note: you can configure ip address, setup TC on dpdkTap. Also you can run your custom socket programs too. You do not need to invest time on TLDP, ANS, VPP as per your requirement you just need an mechanism to inject and receive packet from Kernel network stack.

How do I programm a PC as a PLC that has registers that are readable via Modbus using Beckhoff Twin CAT 3 TCP Modbus?

I would like to use Beckhoff Twin CAT 3 TCP Modbus module to make registers in a PC which is running as a PLC readable via Modbus.
I have downloaded the function Modbus TCP from the Backhoff website. I have followed the example in the Manual TF6250 TwinCAT 3 | Modbus TCP page 55. When I try to read the register at address 0x3000 with a modbus client I get an invalid address error.
The code looks as follows:
PROGRAM MAIN
VAR
ipAddr : STRING(15) := '';
nValue AT%MB0 : ST_EM_Ausgangsdaten_Float;
fbWriteRegs : FB_MBWriteRegs;
bWriteRegs : BOOL;
END_VAR
IF NOT bWriteRegs THEN
nValue.BlindleistungL1 := nValue.BlindleistungL1+1;
nValue.BlindleistungL2 := nValue.BlindleistungL2+1;
nValue.BlindleistungL3 := nValue.BlindleistungL3+1;
bWriteRegs :=TRUE;
fbWriteRegs.sIPAddr :=ipAddr;
fbWriteRegs.nQuantity := 1;
fbWriteRegs.nMBAddr := 16#3000;
fbWriteRegs.cbLength := SIZEOF(nValue);
fbWriteRegs.pSrcAddr := ADR(nValue);
fbWriteRegs.tTimeout := T#5S;
fbWriteRegs(bExecute:=TRUE);
ELSE
IF NOT fbWriteRegs.bBUSY THEN
bWriteRegs :=FALSE;
END_IF
fbWriteRegs(bExecute:=FALSE);
END_IF
Could someone point me to the direction of how to read a variable in a PLC via Modbus.
If I understand your question correctly you are wanting run a Modbus TCP Server (and from your comments it sounds like you have already got something running, but you might not understand exactly why).
I am sure that you know this, but Modbus TCP works by Clients issuing Modbus commands to Read/Write data to/from a Modbus Server and the server responds with the data (or success). The TF6250 communication module allows you to do this in a few ways.
The first issue you have is that the sample code on page 55 you implemented is for the "FB_MBWriteRegs" function. This is a function where your program is acting as a Modbus client (and not a server). It is trying to connect to a remote server and write data to the Modbus address on that server. The description in the manual probably isn't the best and I can see how it may be misleading.
In your case (as it is in the sample code) the STRING ipAddr is empty. I wouldn't be surprised if your fbWriteRegs is reporting an error. You could check this by inspecting the value of the fbWriteRegs.bError and fbWriteRegs.nErrId tags.
For this code to work you would need to connect to an existing Modbus TCP Server and populate the correct IP address.
Additionally, I don't know what data type "ST_EM_Ausgangsdaten_Float" is, but given that this function is for writing to output registers, I wouldn't be surprised if there were issues there as well.
In any case, this isn't what you are wanting to do. I think you will find that if you remove/delete this code and leave your variables mapped as globals it will still 'work'.
What you are probably interested in, is section 4.2 and 4.3.
TF6250 installs a Windows Application that acts as a Modbus TCP server. This server acts as a Modbus to ADS converter which maps values from Modus registers to PLC memory areas via ADS.
You can access the configuration of the Modbus TCP server and the mapping from the TwinCAT Modbus TCP Configuration Tool. For windows this is usually located in the "C:\TwinCAT3\Functions\TF6250-Modbus-TCP" directory. (For Twicat/BSD it is a different procedure all together).
The config app looks like this;
If you click "Get Configuration" - wait a while until it loads, and then "Export Configuration" you can save the mapping/config in a XML file.
The Default mapping is shown on page 19 in section 4.3, which is how I suspect yours is currently working.
If you want to map directly to memory areas rather than via global you will need to know your IndexGroup and Index Offset available here and here. Note: I understand mapping this way improves performance for larger amounts of data but I haven't tested it.
You can manipulate the XML file for the mapping you require. However if you are able to choose whatever memory area you like, I would leave the default configuration for what you want to do and delete the rest of the config, then I would map my data to the appropriate TwinCAT memory area, but that is entirely up to you.
After you have modified your XML file, you can use the Config tool to "Import Configuration" select your modified XML file, and then "Set Configuration" to update the mapping.
You should then be able to use a Modbus Client to connect to your modbus server and know EXACTLY what data is being written to what Modbus address and thus memory area (%M, %Q, %I etc...)
Good luck!

How socketcan get send failure status?

As we all know, in the CAN bus communication protocol, sender know whether the data was successfully sent. I send socketcan data as follows.
ret = write (socket, frame, sizeof (struct can_frame));
However, even if the CAN communication cable is disconnected, the return value of ret is still 16(=sizeof (struct can_frame)).I queried the information and found that the problem was due to the tx_queue of the network stack used by socketcan. When write is called multiple times, the buffer is full and the return value of ret is -1.
But this is not the behavior I expect, I hope that every frame of data sent will immediately get the status of success or failure.
By
echo 0> / sys / class / net / can0 / tx_queue_len
I want to cancel the tx_queue, but it does not work.
What I want to ask is, is there a way to cancel the tx_queue of socketcan, or to get the status of the each sending frame about controller through the API (such as libsocketcan).
Thanks.
You cannot use write() itself to discover whether a CAN frame was successfully put on the bus, because all it does is write the frame to the in-kernel socket buffer. The kernel then moves the frame to the transmit queue of the SocketCAN network interface, followed by the driver moving it to the transmit buffer of the CAN controller, which finally puts the frame on the bus. What you want is a direct write which bypasses all those buffers, but that's not possible with SocketCAN, even if you set the transmit queue length to 0.
However, there is another way to get confirmation. If you enable the CAN_RAW_RECV_OWN_MSGS socket option (see section 4.1.4 and 4.1.7 in the SocketCAN documentation), you will receive frames that were successfully sent. You'll need to use recvmsg() so you get the message flags. msg_flags will have the MSG_CONFIRM bit set for a frames that was successfully sent by the same socket on which it is received. You won't be informed of failures, but you can detect them by using a timeout for the confirmation.
It's not an ideal solution because it mixes the read and write logic in your application. One way to avoid this would be to use two sockets. One for writing and reading MSG_CONFIRM frames, the other for reading all other frames. You could then create a (blocking) write function that does a write() followed by multiple calls to recvmsg() with an appropriate timeout.
Finally, it is useful to enable error frames (through the CAN_RAW_ERR_FILTER socket option). If you send a frame on a socket with a disconnected cable, this will typically result in a bus off state, which will be reported in an error frame.

Single channel gateway only detect first message

My gateway uses the Raspi and RFM95 configuration and operates at 915 MHz. I am using the single channel packet forwarder code by tfelkamp (https://github.com/tftelkamp/single_chan_pkt_fwd).
My gateway only the detects the first message it received and ignores the all messages afterwards. It is still connected to the TTN server but does not receive any more messages.
Can anyone explain what might be the cause of this? Might it because the RFM95 sleeping or the code no longer forwarding the message from the transceiver.
Thanks
I experienced a similar issue. Please note your sender is using different channels, but starts with channel(0). This is the first successful message you receive. Your single channel receiver is just able to receive channel(0). There is a work around for this issue for your sender explained here
This sounds like your transmitter sends the messages using frequency-hopping, while your receiver does not handle it correctly (or the other way around).
Definition of frequency-hopping found in chapter 4.1.1.8 of Semtech's SX1272 datasheet:
Frequency hopping spread spectrum (FHSS) is typically employed when
the duration of a single packet could exceed regulatory requirements
relating to the maximum permissible channel dwell time. This is most
notably the case in US operation where the 902 to 928 MHz ISM band
which makes provision for frequency hopping operation. [...]
If you're using the LMIC-Arduino library for your node then yes, by default it is transmitting in a range and the single_chan_pkt_fwd gateway is only receiving on the frequency you specify in the global_conf.json or the .cpp source (depending on your chosen library).
With the assumption that you're using the arduino-lmic library, make the changes/additions mentioned in the this TTN forum post linked by Rainer which is the same I ran into.
Also... you'll find this further down the thread: in src > lmic > lmic.c edit the following:
void LMIC_disableChannel (u1_t channel) {
if( channel < 72+MAX_XCHANNELS )
//LMIC.channelMap[channel>>4] &= ~(1<<(channel&0xF)); // comment this one
LMIC.channelMap[channel/16] &= ~(1<<(channel&0xF)); // add this one
}
Then pick a frequency on channel 0 and set that for both node and packet forwarder. Here's a table snip from this page. I went with 902300000 and it's working fine.
"freq": 902300000,
"spread_factor": 7,

Can I find out the status of the port using the Lua "socket" library?

Help me track the status of a specific port: "LISTENING", "CLOSE_WAIT", "ESTABLISHED".
I have an analog solution with the netstat command:
local command = 'netstat -anp tcp | find ":1926 " '
local h = io.popen(command,"rb")
local result = h:read("*a")
h:close()
print(result)
if result:find("ESTABLISHED") then
print("Ok")
end
But I need to do the same with the Lua socket library.
Is it possible?
Like #Peter said, netstat uses the proc file system to gather network information, particularly port bindings. LuaSockets has it's own library to retrieve connection information. For example,
Listening
you can use master:listen(backlog) which specifies the socket is willing to receive connections, transforming the object into a server object. Server objects support the accept, getsockname, setoption, settimeout, and close methods. The parameter backlog specifies the number of client connections that can be queued waiting for service. If the queue is full and another client attempts connection, the connection is refused. In case of success, the method returns 1. In case of error, the method returns nil followed by an error message.
The following methods will return a string with the local IP address and a number with the port. In case of error, the method returns nil.
master:getsockname()
client:getsockname()
server:getsockname()
There also exists this method:
client:getpeername() That will return a string with the IP address of the peer, followed by the port number that peer is using for the connection. In case of error, the method returns nil.
For "CLOSE_WAIT", "ESTABLISHED", or other connection information you want to retrieve, please read the Official Documentation. It has everything you need with concise explanations of methods.
You can't query the status of a socket owned by another process using the sockets API, which is what LuaSocket uses under the covers.
In order to access information about another process, you need to query the OS instead. Assuming you are on Linux, this usually means looking at the proc filesystem.
I'm not hugely familiar with Lua, but a quick Google gives me this project: https://github.com/Wiladams/lj2procfs. I think this is probably what you need, assuming they have written a decoder for the relevant /proc/net files you need.
As for which file? If it's just the status, I think you want the tcp file as covered in http://www.onlamp.com/pub/a/linux/2000/11/16/LinuxAdmin.html