[APP][Pro] FTP Client - Control FTP Servers through a directory-based UI in the Homey App or Web App

I’m trying Elevenlabs text-to-speech (in mp3 file format and in mp3 streaming format) on Homey 2023 advanced flow. The result with Micro Web Server is a few byte file content, which is obviously not a valid mp3. The only option I see is the card to save a file(base64), or is this only for images?

How can I play the mp3 on Sonos or Google Chromecast using a needed file URL.

The POST result is bigger than a few bytes:

(Yes, this is the same post as in Micro Web Server, because I don’t know where my question belongs to)

Well, the way you are trying to do it now, is not possible.
You are executing a POST request. It looks like the result is a real/binary MP3 file. But the post-request-flowcard will return its value as a text/string. This will never work.

This is why the FTP client can save files that are converted to base64, its an encoded (not encrypted) “version” of a file in textform.

Homey (flows) cannot handle binary files in any way.

Two questions:

  1. Is there an option in the API to return the file as base64 instead of binary?
  2. Do you require the Elevenlabs TTS?
    Because you could otherwise use the TTS from the Google Services app?!

Thanks for your rection!

My answers:

  1. not that I know; I have tried the 2 options: getting a mp3 file or a mp3 stream
  2. I know and use the TTS Google Services, but Elevenlabs has way more and better sounding voices with more options.

Could BLL or Homeyscript be an option? Is Google Services app using a mp3 as well? If yes, than Elevenlabs could be an extra option to stream to Google devices…

EDIT from Google site about Google Text-to-speech api:
" The Text-to-Speech API returns the synthesized audio as base64-encoded data contained in the JSON output. The JSON output in the synthesize-text.txt file looks similar to the following code snippet.

{
  "audioContent": "//NExAASCCIIAAhEAGAAEMW4kAYPnwwIKw/BBTpwTvB+IAxIfghUfW.."
}

To decode the results from the Text-to-Speech API as an MP3 audio file, run the following command from the same directory as the synthesize-text.txt file.

cat synthesize-text.txt | grep 'audioContent' | \
sed 's|audioContent| |' | tr -d '\n ":{},' > tmp.txt && \
base64 tmp.txt --decode > synthesize-text-audio.mp3 && \
rm tmp.txt
"

Well, yes, i think so.
With HomeyScript you could also execute a http-post. The returning value would be a binary mp3 file, which you can than convert to base64 and save on through the FTP client app.

Is this about Elevenlabs?

It’s about the Google text-to-speech api. I have edited my post.

Not sure why you wrote it than?
I know Google TTS gives me the file as base64 yeah.
But Google TTS is not an option for you right?

Anyway, i just looked at Elevenlabs tts api, but it doesnt seem to have an option to deliver the file as base64.

So, only way to do it is with a HomeyScript.

I wrote it as an answer to my own question:

@Amersfoort
Can you PM me the inside of your POST flowcard, ill create a HS script for you then. But i need the key to test it.

1 Like

Use the HomeyScript return a Text flowcard.
Than fill this script.
The tag it will generate will have the MP3 file in base64.
That you can save to the FTP with the save base64 as file flowcard.

let call = await fetch("https://api.elevenlabs.io/v1/text-to-speech/XrExE9yKIg1WjnnlVkGX?enable_logging=true&output_format=mp3_44100_96", {
  method: "POST",
  body: JSON.stringify(
    {"text":"Dit is een test file","model_id":"eleven_multilingual_v2","voice_settings":{"stability":0.5,"similarity_boost":0.75,"style":0,"use_speaker_boost":true}}
  ),
  headers: {
    "Content-type": "application/json; charset=UTF-8",
    "xi-api-key":"FILL YOUR KEY"
  }
});

let mp3 = await call.buffer();

let base64 = Buffer.from(mp3).toString('base64');
return base64;
2 Likes

Yes, it’s working! Thank you @Arie_J_Godschalk!

Here is my flow:

2 Likes

Cool. Arie’s magic haha.

While this works fine,
I wonder / thinking out loud: once the mp3 file is fetched, you don’t need to fetch it everytime you need it?

The first two flow cards can be omitted to play the mp3 once it’s available from the mp3 folder, so it’s independent from internet.

1 Like

You’re right, but I use it for news headlines and other dynamic texts. That’s why I have to generate the text-to-speech each time again.

2 Likes

I am trying to save a Simple (Sys) Log file to my Synology NAS. I have a Homey Pro 2023.

I created a new custom FTP Client device. Entered the login credentials of my NAS in de settings section of the device. But it does not seem to establish a connection. I get the following error (see screenshot) when trying to select a folder in the flow card.

I connect securely to my NAS (so the Secure option in the FTP Client’s settings is set to Yes); I tried both the SFTP and FTPS ports, but the error remains. I also checked that the user account has access to the root folder set in the FTP Client’s settings. Which it has. I restarted the FTP Client app, but that did not help.

I read in this thread that another user had a somewhat similar problem, but I could not find a follow-up on how that was solved.

I don’t know what I am doing wrong. Hope someone can point me in the right direction.

Restart FTP client app, then try again and send me a diagnostic after?

Thanks for your quick response!
Diagnostic report created: 39c3ab98-c49b-4f19-b0e4-f8dafc88459e

It looks like your SSL certificate is not valid, since you are using an IP to connect:

Note: this log has been manually submitted by a user. Log ID: 39c3ab98-c49b-4f19-b0e4-f8dafc88459e User Message: Error 'Client is closed because server closed connection unexpectedly' when trying to connect to a Synology NAS via either SFTP or FTPS. stdout: valid_from: 'Feb 10 00:00:00 2024 GMT', valid_to: 'Mar 12 23:59:59 2025 GMT', fingerprint: '4C:DC:B6:8B:7E:DA:5D:44:88:09:1F:21:66:B3:72:97:2C:BA:01:84', fingerprint256: '4D:82:9C:B1:F4:1B:60:03:BD:02:87:C0:00:D2:8F:5D:3F:87:2F:DF:24:85:3A:F3:FF:BF:D2:96:E4:53:A4:2F', fingerprint512: '8E:23:6D:91:3A:C4:1F:84:F4:E8:6B:1B:0A:4F:08:DC:5B:6C:45:60:4E:3B:E4:0B:28:EF:3F:3F:B6:50:45:D3:20:B1:2F:4E:66:D8:04:65:1B:AF:08:AD:56:AA:02:A3:36:53:1B:28:A4:EA:8A:B6:7E:58:52:15:4A:8D:76:25', ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ], serialNumber: '06938CD81F448E65B0762AE14919EC2F', raw: , issuerCertificate: { subject: [Object: null prototype], issuer: [Object: null prototype], infoAccess: [Object: null prototype], ca: true, modulus: 'BFB9592544123516E25D5049050AE0CBFC8DDA25089A67A6A26D11E36A9FDAA7DCF2D5A60DAE985EED871A3703283EC66F5C347E84D24EA3D81B80E6154CFABC81773CE08EF960A38789503836B249419EA9DAC250CAAC7AD07904223CC837ED4B40B7D74E5A6ECE74E839AD61C930F4CB28AD172398C1444CFBF088F05345329061C36DA1A5E01090E38B9ACA93E5064961E8A4EEA96F9FC81F0FE5DD0E7937924BAEBB4786FAFBB2AD21ABE6E5F92D18455A5BF5CC5403721FC42A6775EB79BACFFC9CC7FA8B6BDCF2BC82DCEDC4296FE93B4CBADAF56135ED83D29FD00D8C6F840A8F4F0D6DCDF65C2129008DBF0D601A882EC8242EEC713B0675BC792485', bits: 2048, exponent: '0x10001', pubkey: , valid_from: 'Nov 2 12:24:33 2017 GMT', valid_to: 'Nov 2 12:24:33 2027 GMT', fingerprint: 'CB:FE:9E:B4:3B:3B:37:FE:0D:FB:C4:C2:EB:2D:4E:07:D0:8B:D8:E8', fingerprint256: '44:22:E9:63:EE:53:CD:58:CC:9F:85:CD:40:BF:5F:FE:C0:09:5F:DF:1A:15:45:35:66:1C:1C:06:BC:AD:C6:9B', fingerprint512: '72:DA:2F:AA:57:86:09:E4:01:A7:70:D5:A6:F1:B5:E6:45:E3:BD:8E:FB:D8:AB:91:D7:FB:38:DE:F5:FD:9F:95:3E:C2:58:30:27:B1:AD:10:C6:2D:90:D3:AD:BF:63:C8:E4:26:1A:4F:6E:4F:51:92:B5:AB:2D:B7:DE:34:8F:C7', ext_key_usage: [Array], serialNumber: '0B259422CED9812A15A04E99528A0EFA', raw: , issuerCertificate: [Object] } }, code: 'ERR_TLS_CERT_ALTNAME_INVALID' } > CWD / > QUIT Trying to find optimal transfer strategy... Connected to 10.0.0.248:21 (No encryption) < 220 DISKSTATION FTP server ready. > AUTH TLS < 234 AUTH TLS command successful. Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: IP: 10.0.0.248 is not in the cert's list: at new NodeError (node:internal/errors:405:5) at Object.checkServerIdentity (node:tls:337:12) at TLSSocket.onConnectSecure (node:_tls_wrap:1669:27) at TLSSocket.emit (node:events:517:28) at TLSSocket._finishInit (node:_tls_wrap:1070:8) at ssl.onhandshakedone (node:_tls_wrap:856:12) { reason: "IP: 10.0.0.248 is not in the cert's list: ", host: '10.0.0.248', cert: { subject: [Object: null prototype] { CN: 'diskstation.vandenbeucken.net' }, issuer: [Object: null prototype] { C: 'US', O: 'DigiCert Inc', OU: 'www.digicert.com', CN: 'RapidSSL TLS RSA CA G1' }, subjectaltname: 'DNS:diskstation.vandenbeucken.net, DNS:www.diskstation.vandenbeucken.net', infoAccess: [Object: null prototype] { 'OCSP - URI': [Array], 'CA Issuers - URI': [Array] }, ca: false, modulus: '94C2AAF03330FAF0208BE49ECA54E39FEA06BAC0FA0C6CA82A1CDCD23BE56C262AFAAD915904F02E88C35817F26D1001901A90175B96B9B079F4CF29AE0EC1C6CBE8BAA97A465197E9412600616DFE8392DBBBB0A6EB5EDD8F6C70D9D978B7BBA861AC65B1966A01BE8F0618A6ADC6B961A4EE89D1FC75016DC97FC0BDDC44EEAA069CF2904166C17A9D94C6E50BEA5AEB5EFCADA8E559D65DA6A7EE724C40DAED6AF0BBE6F1678AEF7A8FBA3184C2B73BD3C3BFD0A96261796622EF812D603BD26E44E5BCB058498384E657F8CB79582D636AE9A61AA6D497BBBAA62EB0FE2A258F08E2C8D4F15DAFACBE8E0FF8F1922DD0B4647231D2CCD119A53D466708E2930BF22F9F6D4146D2AA5343EA69B401724BD93DD6EFE1C8A5565F0B8A2EA4ADFB47076B116C8F551E5964544DDA9B7FC059623838FBF80DB73B98086C7C533BC04654641E83CD0C4D4B99957C940958A5E15633C3E29A09FC8771C31C1BEC6E883C4AFC78CAC21092E5AAE7B5D4D1DDAE268D4AE4DA80E7EB7C90CFB4CDA2939340D71F6D347E53D32142ED84CF79AC93EB8AF627AF0E35885BF6B496FC0166667E27DBF4F32891B4457FA234983A8503887E5FB732F86C1A0F712505B021CE97449EC32DA33005EEC56E33234324408D5D945F821E34A9E7EDCBFFC502340F70CF95A45AAD4D5D235A23F48B7A538526782614BBE598D9478CAA8F60BC9E97', bits: 4096, exponent: '0x10001', pubkey: , valid_from: 'Feb 10 00:00:00 2024 GMT', valid_to: 'Mar 12 23:59:59 2025 GMT', fingerprint: '4C:DC:B6:8B:7E:DA:5D:44:88:09:1F:21:66:B3:72:97:2C:BA:01:84', fingerprint256: '4D:82:9C:B1:F4:1B:60:03:BD:02:87:C0:00:D2:8F:5D:3F:87:2F:DF:24:85:3A:F3:FF:BF:D2:96:E4:53:A4:2F', fingerprint512: '8E:23:6D:91:3A:C4:1F:84:F4:E8:6B:1B:0A:4F:08:DC:5B:6C:45:60:4E:3B:E4:0B:28:EF:3F:3F:B6:50:45:D3:20:B1:2F:4E:66:D8:04:65:1B:AF:08:AD:56:AA:02:A3:36:53:1B:28:A4:EA:8A:B6:7E:58:52:15:4A:8D:76:25', ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ], serialNumber: '06938CD81F448E65B0762AE14919EC2F', raw: , issuerCertificate: { subject: [Object: null prototype], issuer: [Object: null prototype], infoAccess: [Object: null prototype], ca: true, modulus: 'BFB9592544123516E25D5049050AE0CBFC8DDA25089A67A6A26D11E36A9FDAA7DCF2D5A60DAE985EED871A3703283EC66F5C347E84D24EA3D81B80E6154CFABC81773CE08EF960A38789503836B249419EA9DAC250CAAC7AD07904223CC837ED4B40B7D74E5A6ECE74E839AD61C930F4CB28AD172398C1444CFBF088F05345329061C36DA1A5E01090E38B9ACA93E5064961E8A4EEA96F9FC81F0FE5DD0E7937924BAEBB4786FAFBB2AD21ABE6E5F92D18455A5BF5CC5403721FC42A6775EB79BACFFC9CC7FA8B6BDCF2BC82DCEDC4296FE93B4CBADAF56135ED83D29FD00D8C6F840A8F4F0D6DCDF65C2129008DBF0D601A882EC8242EEC713B0675BC792485', bits: 2048, exponent: '0x10001', pubkey: , valid_from: 'Nov 2 12:24:33 2017 GMT', valid_to: 'Nov 2 12:24:33 2027 GMT', fingerprint: 'CB:FE:9E:B4:3B:3B:37:FE:0D:FB:C4:C2:EB:2D:4E:07:D0:8B:D8:E8', fingerprint256: '44:22:E9:63:EE:53:CD:58:CC:9F:85:CD:40:BF:5F:FE:C0:09:5F:DF:1A:15:45:35:66:1C:1C:06:BC:AD:C6:9B', fingerprint512: '72:DA:2F:AA:57:86:09:E4:01:A7:70:D5:A6:F1:B5:E6:45:E3:BD:8E:FB:D8:AB:91:D7:FB:38:DE:F5:FD:9F:95:3E:C2:58:30:27:B1:AD:10:C6:2D:90:D3:AD:BF:63:C8:E4:26:1A:4F:6E:4F:51:92:B5:AB:2D:B7:DE:34:8F:C7', ext_key_usage: [Array], serialNumber: '0B259422CED9812A15A04E99528A0EFA', raw: , issuerCertificate: [Object] } }, code: 'ERR_TLS_CERT_ALTNAME_INVALID' } > CWD > QUIT Trying to find optimal transfer strategy... finally stderr: 2024-08-03T12:10:42.511Z [err] Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) 2024-08-03T12:10:42.513Z [err] [ManagerDrivers] [Driver:ftpconnection] action_ftpclient_save_file_base64.directory.registerAutocompleteListener.error : Error: None of the available transfer strategies work. Last error response was 'Error: Client is closed because Server closed connection unexpectedly.'. at Client.prepareTransfer (/app/node_modules/basic-ftp/dist/Client.js:700:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client.list (/app/node_modules/basic-ftp/dist/Client.js:484:13) at async FtpClient.exec (/app/lib/ftp-client.js:55:14) at async FtpClientDriver.getFiles (/app/drivers/ftpconnection/driver.js:299:17) at async /app/drivers/ftpconnection/driver.js:254:24 2024-08-03T12:18:39.843Z [err] Error: Client is closed because Server closed connection unexpectedly. at /app/node_modules/basic-ftp/dist/FtpContext.js:226:29 at new Promise () at FTPContext.handle (/app/node_modules/basic-ftp/dist/FtpContext.js:208:16) at FTPContext.request (/app/node_modules/basic-ftp/dist/FtpContext.js:186:21) at Client.send (/app/node_modules/basic-ftp/dist/Client.js:116:25) at Client.cd (/app/node_modules/basic-ftp/dist/Client.js:267:21) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async FtpClient.exec (/app/lib/ftp-client.js:30:9) at async FtpClientDriver.getFiles (/app/drivers/ftpconnection/driver.js:299:17) at async /app/drivers/ftpconnection/driver.js:254:24 Closing reason: Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) { code: '0' } 2024-08-03T12:18:39.846Z [err] Error: None of the available transfer strategies work. Last error response was 'Error: Client is closed because Server closed connection unexpectedly.'. at Client.prepareTransfer (/app/node_modules/basic-ftp/dist/Client.js:700:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client.list (/app/node_modules/basic-ftp/dist/Client.js:484:13) at async FtpClient.exec (/app/lib/ftp-client.js:43:14) at async FtpClientDriver.getFiles (/app/drivers/ftpconnection/driver.js:299:17) at async /app/drivers/ftpconnection/driver.js:254:24 2024-08-03T12:18:39.896Z [err] Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) 2024-08-03T12:18:39.898Z [err] [ManagerDrivers] [Driver:ftpconnection] action_ftpclient_save_file_base64.directory.registerAutocompleteListener.error : Error: None of the available transfer strategies work. Last error response was 'Error: Client is closed because Server closed connection unexpectedly.'. at Client.prepareTransfer (/app/node_modules/basic-ftp/dist/Client.js:700:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client.list (/app/node_modules/basic-ftp/dist/Client.js:484:13) at async FtpClient.exec (/app/lib/ftp-client.js:55:14) at async FtpClientDriver.getFiles (/app/drivers/ftpconnection/driver.js:299:17) at async /app/drivers/ftpconnection/driver.js:254:24 2024-08-03T13:00:02.750Z [err] Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) 2024-08-03T13:00:02.753Z [err] Error: Client is closed because Server closed connection unexpectedly. at /app/node_modules/basic-ftp/dist/FtpContext.js:226:29 at new Promise () at FTPContext.handle (/app/node_modules/basic-ftp/dist/FtpContext.js:208:16) at FTPContext.request (/app/node_modules/basic-ftp/dist/FtpContext.js:186:21) at Client.send (/app/node_modules/basic-ftp/dist/Client.js:116:25) at Client.cd (/app/node_modules/basic-ftp/dist/Client.js:267:21) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async FtpClient.exec (/app/lib/ftp-client.js:30:9) at async FtpClientDriver.saveFile (/app/drivers/ftpconnection/driver.js:593:16) at async /app/drivers/ftpconnection/driver.js:239:17 Closing reason: Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) { code: '0' } 2024-08-03T13:00:02.756Z [err] Error: None of the available transfer strategies work. Last error response was 'Error: Client is closed because Server closed connection unexpectedly.'. at Client.prepareTransfer (/app/node_modules/basic-ftp/dist/Client.js:700:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client._uploadFromStream (/app/node_modules/basic-ftp/dist/Client.js:388:13) at async FtpClient.exec (/app/lib/ftp-client.js:43:14) at async FtpClientDriver.saveFile (/app/drivers/ftpconnection/driver.js:593:16) at async /app/drivers/ftpconnection/driver.js:239:17 2024-08-03T13:00:02.807Z [err] Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) 2024-08-03T13:00:26.660Z [err] Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) 2024-08-03T13:00:26.664Z [err] Error: None of the available transfer strategies work. Last error response was 'Error: Client is closed because Server closed connection unexpectedly.'. at Client.prepareTransfer (/app/node_modules/basic-ftp/dist/Client.js:700:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client.list (/app/node_modules/basic-ftp/dist/Client.js:484:13) at async FtpClient.exec (/app/lib/ftp-client.js:43:14) at async FtpClientDriver.getFiles (/app/drivers/ftpconnection/driver.js:299:17) at async /app/drivers/ftpconnection/driver.js:254:24 2024-08-03T13:00:26.716Z [err] Error: Server closed connection unexpectedly. at Socket. (/app/node_modules/basic-ftp/dist/FtpContext.js:130:37) at Socket.emit (node:events:529:35) at TCP. (node:net:350:12) 2024-08-03T13:00:26.719Z [err] [ManagerDrivers] [Driver:ftpconnection] action_ftpclient_save_file_base64.directory.registerAutocompleteListener.error : Error: None of the available transfer strategies work. Last error response was 'Error: Client is closed because Server closed connection unexpectedly.'. at Client.prepareTransfer (/app/node_modules/basic-ftp/dist/Client.js:700:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client.list (/app/node_modules/basic-ftp/dist/Client.js:484:13) at async FtpClient.exec (/app/lib/ftp-client.js:55:14) at async FtpClientDriver.getFiles (/app/drivers/ftpconnection/driver.js:299:17) at async /app/drivers/ftpconnection/driver.js:254:24

I am connecting to my Synology NAS via the LAN IP. Some services on the NAS are accessible via the internet. The certificate installed on the NAS is linked to my external domain name; not the internal LAN IP range.

If change the IP in the FTP Client’s settings to my external domain name, then I get an ‘connection refused error’ for my external/WAN address. I tried granting access to both the SFTP and FTPS services, by adding my external IP adress in the NAS’s firewall, but still get the connection refused error (also after restarting the FTP Client).

Not sure whether it is relevant: I also use FTPS with another Homey app (Exporteer/Archive Insights) and that allows me to establish a secure FTPS connection to my LAN IP, without any certificate issues.

Any suggestions how to get the secure connection working?

Not at this moment no.

Okay, ill have a look at how this app does the SFTP security, but tbh, if the Certificate fails, it should not work.
But perhaps a setting can be used to accept failty Certificates.
Im going on holiday however Monday, so can you create a support ticket?
Thanks!

I have created a ticket. And also sent you a token of appreciation via PayPal :slightly_smiling_face:
Enjoy your holiday!

1 Like