[SOLVED] Newline in Twilio SMS message. (Was: Call-service API error.... extra keys not allowed in Node-Red flow)

Total newbie to HA here. I got it installed on the R-Pi last night and managed to get my Schlage Connect z-wave deadbolt talking to HA. I also got node-red and Twilio installed and configured and working.

I’m playing around with node-red flows and created a flow to send a Twilio text message to my phone when the state of the deadbolt changes. The flow looks like:

The function node takes the msg payload from the deadbolt state change event and creates a new field, msg.textMessage, with the text that I want to send to my phone. The debug node shows that the text string is what I want it to be.

The Twilio SMS node has the following JSON in the data field:

{ "message": msg.textMessage, "target": "+1<myPhoneNumber>"}

When I do this, I get an error in the node red debug console:

"Call-service API error. Error Message: extra keys not allowed @ data['0']"

If I replace the msg.textMessage with a hardcoded string, it works.

How do I use a variable as the text I want to send to my phone?

Hi

Variables need to be wrapped in curly braces. Try

{ "message": "{{ msg.textMessage }}", "target": "+1<myPhoneNumber>" }

Thanks! That moved me on to a new error message! :slightly_smiling_face:

Feel free to share, we’ve all been through that :grin:

I’m either getting the same error, or an error indicating that the SMS message is an empty string, based on whether I use “msg.textMessage” or just “textMessage” in the JSON. So I’m not sure I’m properly referencing my variable.

You don’t usually need the msg bit, now I come to think of it. E.g. msg.payload is {{ payload }}.

What’s the output of the debug node?

OK, this is odd. Here’s my function:

old_state = msg.data.old_state.state;
new_state = msg.data.new_state.state;

old_status = msg.data.old_state.attributes.lock_status;
new_status = msg.data.new_state.attributes.lock_status;

old_time = msg.data.old_state.last_changed;
new_time = msg.data.new_state.last_changed;

new_time_local = new Date(new_time);

textMessage = "The front door deadbolt changed state.\n";
textMessage += "  Old state: "
textMessage += old_state;
textMessage += " - ";
textMessage += old_status;

textMessage += "\n\n";

textMessage += "  New state: "
textMessage += new_state;
textMessage += " - ";
textMessage += new_status;

textMessage += "\n\n";
textMessage += "Date/time: ";
textMessage += new_time_local;

msg.textMessage = textMessage;

msg.textMessage2 = "Test message 2.";

return msg;

If I send textMessage2 to Twilio, the text message is sent and received by my phone. If I send textMessage, I get:

"Call-service API error. Error Message: extra keys not allowed @ data['0']"

Per the debug node, the msg object (after going through a JSON pretty-printer) is:

{
  "topic": "<reallyLongDeviceName>",
  "payload": "locked",
  "data": {
    "entity_id": "<reallyLongDeviceName>",
    "old_state": {
      "entity_id": "<reallyLongDeviceName>",
      "state": "unlocked",
      "attributes": {
        "node_id": 6,
        "value_index": 0,
        "value_instance": 1,
        "value_id": "<redacted>",
        "notification": "Manual Lock",
        "lock_status": "Manually Locked by Key Cylinder or Inside thumb turn",
        "friendly_name": "<friendlyName>"
      },
      "last_changed": "2020-04-29T01:14:33.032447+00:00",
      "last_updated": "2020-04-29T01:14:33.032447+00:00",
      "context": {
        "id": "<redacted>",
        "parent_id": null,
        "user_id": "<redacted>"
      }
    },
    "new_state": {
      "entity_id": "<reallyLongDeviceName>",
      "state": "locked",
      "attributes": {
        "node_id": 6,
        "value_index": 0,
        "value_instance": 1,
        "value_id": "<redacted>",
        "notification": "Manual Lock",
        "lock_status": "Manually Locked by Key Cylinder or Inside thumb turn",
        "friendly_name": "<friendlyName>"
      },
      "last_changed": "2020-04-29T01:16:48.925835+00:00",
      "last_updated": "2020-04-29T01:16:48.925835+00:00",
      "context": {
        "id": "<redacted>",
        "parent_id": null,
        "user_id": "<redacted>"
      },
      "timeSinceChangedMs": 55
    }
  },
  "_msgid": "38ff9f0.dc16862",
  "textMessage": "The front door deadbolt changed state.\n  Old state: unlocked - Manually Locked by Key Cylinder or Inside thumb turn\n\n  New state: locked - Manually Locked by Key Cylinder or Inside thumb turn\n\nDate/time: Tue Apr 28 2020 20:16:48 GMT-0500 (Central Daylight Time)",
  "textMessage2": "Test message 2."
}

So what’s wrong with my textMessage string that the Twilio SMS sender thingy doesn’t like it?

Aha! It seems that Twilio doesn’t like the ‘\n’ character in the text message. Per this page, Twilio says I should use ‘%0a’ instead of ‘\n’ but when I do that I get a literal ‘%0a’ in the text message.

At least the text gets delivered, though… on to the next problem! :slight_smile:

Okay, I’ve troubleshooted until beer-thirty. Giving it a rest for the night.

When I use an Automation in HA rather than node red, I can use ‘\n’ without getting an error. That gets delivered as a string literal, however, as does ‘%0a’. Neither produces a new line in the received text message.

Anyone know how to get a line break (newline) in a message to twilio_sms? (I might have to create a new post with a more appropriate title, I think…)

Did I say I was giving it a rest for the night?

Okay, so the link I provided above to the Twilio site says that the ‘%0a’ string should be used when one of Twilio’s helper libraries isn’t being used.

I looked at the HA source code, and core/homeassistant/components/twilio/inti.py does import and use Client from twilio.rest, so from the Twilio side, the ‘\n’ character should work.

Therefore, I suspect that either node red, or HA, or both, are not passing along the ‘\n’ character as expected. I don’t have the skills (or motivation) to dig in and debug that right now, but it seems to me that this is likely a bug in either HA or nodered or both.

SOLVED!

I looked at the code for the call-service node in the HA node-red repo. That node is using JSON.parse() internally. Per this link, I need to escape \n as \\n. That does, in fact, do the trick.