How to display text file on async Webserver using esp8266 - arduino

I have several txt files on my SD card that I would like to output to my async webserver. I use the ESP8266 for this.
I have tried it with the following call. However, an error is then displayed.
It also says that two SD.h libraries were found:
Library/Arduino15/packages/esp8266/hardware/esp8266/3.0.2/libraries/SD
/Applications/Arduino.app/Contents/Java/libraries/SD
the latter is not used.
The error I get is the following:
no matching function for call to 'AsyncWebServerRequest::send(SDClass&, const char [12], const char [10])'
how can I solve this problem?
server.on("/getdata", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/subj1_1.txt", "text/plain");
});

Related

Firebase Functions, node-7z - Function works locally but throws error in production

I am new to Firebase Functions and backend dev in general. I have written a function (called convertFile) that uses the node package "node-7z" to unzip a file called "example.7z" (located in the root of my functions directory). This is my functions code:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const sevenZipBin = require("7zip-bin");
const { extractFull } = require("node-7z");
admin.initializeApp();
const pathTo7za = sevenZipBin.path7za;
exports.convertFile = functions.https.onCall((data, context) => {
const seven = extractFull('./example.7z', './example', {
$bin: pathTo7za
});
seven.on('error', function (err) {
console.log(err.message);
});
seven.on('end', function () {
console.log('END');
});
});
When I use Firebase's local emulator to run the function, the function runs successfully. A new directory called "example" containing the contents of "example.7z" is created within my "functions" directory (this is the desired behavior). When I deploy the function to firebase, and run the function in production, I get the following error in the function log (image of full log shown at the bottom):
spawn /workspace/node_modules/7zip-bin/linux/x64/7za EACCES
Note that "/workspace/node_modules/7zip-bin/linux/x64/7za" is the filepath stored in the variable "sevenZipBin.path7za".
I can understand how there might be a permissions issue when the function is run on firebase as opposed to my local system, but I don't know how to solve the issue. I tried using a child process (within the function) to change the file permissions using the "chmod" command, but I get this error in the functions log:
chmod: changing permissions of '/workspace/node_modules/7zip-bin/linux/x64/7za': Read-only file system
I assume this is not a valid solution. I tried searching Google, stackoverflow, Github, etc. for solutions but I still don't know how to proceed from here. If anyone has suggestions, I would greatly appreciate it.
Additional info:
node-7z docs - https://github.com/quentinrossetti/node-7z
7zip-bin docs - https://github.com/develar/7zip-bin
Screenshot of functions log

React Native Expo: Base64 Image not uploading to Firebase Storage using any upload method

I am trying to upload a base64 image to Firebase Storage using React Native Expo. The image I am uploading is taken through the takePictureAsync method in expo-camera library with the following CameraPictureOptions
quality:1
base64:true
exif:false
Next, I store this image in a state variable, named photo, and display it to the user in the app using the Image tag with the uri:
data:image/jpg;base64" + photo.base64
Now when uploading it I first tried the uploadString method as per the firebase storage documentation as below
uploadString(storageRef, photo.base64, 'base64').then((snapshot) => {
console.log('Uploaded a raw string!');
});
But it gave the error message
Unhandled promise rejection: FirebaseError: Firebase Storage: String does not match format 'base64': Invalid character found (storage/invalid-format)
I tried this with other parameters instead of base64 ("data_url", "base64url", and not putting anything in the parameter), but I got essentially the same error for "data_url" and "base64url", and when I don't put anything in the parameter the app crashes. After this I looked online to find a fix, and one issue that that some people brought up to explain this error message was that to decode and encode the base64 string firebase storage used the atob and btoa method respectively, but this did not work in javascript/was deprecated. To that end, the fix that was suggested was adding this to on top of App.js
import {decode, encode} from 'base-64';
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob)
{
global.atob = decode;
}
However, when I did this the app crashed after the button was pressed that triggered the uploadString method.
After this, I tried using the uploadBytes method as per the documentation. I first tried passing the uri string ("data:image/jpg;base64, base64 data) as input, as below. While this did make the image visible on my firebase storage, the image could not be opened. I think this was because this method expected a File or a Blob as input and the input I gave was a base64 string
uploadBytes(storageRef, uri).then((snapshot) => {
console.log('Uploaded a blob or file!');
});
Next, I looked online for ways to convert the base64 string to a Blob. The first approach I tried was calling the fetch api on uri and the blob function to get the blob and then put that in the uploadBytes function.
const response = await fetch(uri)
const blob = await response.blob()
uploadBytes(storageRef, blob).then((snapshot) => {
console.log('Uploaded a blob or file!');
});
However, I get the following error message, which I was unable to solve.
Error: ENOENT: no such file or directory, open pathToReactNativeApp/http:/LocalIPAddress:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&strict=false&minify=false'
Next, I tried the following to get the blob as suggested here, but this lead the app to crash.
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError("Network request failed"));
};
// on complete
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
Can someone please guide me on how I can upload this base64 image to firebase storage? Any help would be greatly appreciated!
ImagePicker.launchImageLibraryAsync from expo, will return uri, (no need to include base64 :true)
using that uri generate blob
const response = await fetch(result.uri);
const blob = await response.blob();
using this blob, upload to firebase storage using uploadBytes function
uploadBytes(ref, blob).....
i m using firebase 9 web moduler, will run in all platforms
uploading blob is far batter than using base64 and speedy aswell.
not only images, you can upload videos aswell with this,

Get request URL in Arduino web server

Am trying to display whatever value is sent to my Arduino (mega + WiFi r3) web server how do I do it ? Thanks in advance.
Using this sample, the server listens for "ledOn" and then performs an action but I want the server to listen to any request coming from clients and display the requests in the serial monitor.
server.on("ledOn", [](){
// My code
});
You use the ESP8266WebServer library in the ESP8266 on the combined board. The reference is in the README file and the library has good examples.
The function to get the request's URL is server.uri().
Usually to process the GET request the URL is not read with uri() function, but the resource part (the 'path') is matched with the on() functions in setup() as server.on("some/path", fncToHandle); and the URL parameters of a GET request are parsed by the WebServer library and made available with a set of functions:
const String & arg();
const String & argName();
int args();
bool hasArg();
the standard url parameters are after ? in form of name=value, separated by & like
/some/path?name=John&lastName=Smith
snippets from SimpleAuthentication example:
from setup()
server.on("/login", handleLogin);
from handleLogin:
if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")) {
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin") {

File download from API to Meteor server and upload to S3

I am sending a request from my Meteor server to download a file via an API. I then want to upload that file to S3. I keep getting the following "NoSuchKey: The specified key does not exist." I initially thought it was maybe a problem with my AcessKey/SecretKey form AWS but after googling this for a while the only examples I could find of other people getting this error is when trying to download a file from S3.
Setting up cfs:s3
var imageStore = new FS.Store.S3("images", {
accessKeyId: "MyAcessKeyId", //required if environment variables are not set
secretAccessKey: "MySecretAcessKey", //required if environment variables are not set
bucket: "BucketName", //required
});
Images = new FS.Collection("images", {
stores: [imageStore]
});
Start file transfer from API and upload to S3
client.get_result(id, Meteor.bindEnvironment(function(err, result){ //result is the download stream and id specifies which file to download.
if (err !== null){
return;
}
var file = new FS.File(result);
Images.insert(file, function (err, fileObj) {
if (err){
console.log(err);
}
});
}));
Note: I was getting the following error so I added Meteor.bindEnvironment.
"Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment."
Node.js example from API Documentation
client.get_result(id, function(err, result){
if (err != null) {
return;
}
file.writeFile(path.join('public', path.join('results', filename)), result, 'binary');
});
What ended up fixing the problem for me was moving part of the setup to the lib folder. Although I tried several different ways I was unable to get it to execute entirely on the server. It looks like the documentation was updated recently which states everything a bit more clearly. If you follow this setup it should eliminate the error. See the section titled Client, Server, and S3 credentials
https://github.com/CollectionFS/Meteor-CollectionFS/tree/master/packages/s3
Note: Make sure not to place you secret key is not in you lib folder as this is accessible from the client.

Wrapping Asynchronous NPM in Meteor

I am using meteor-npm to use NPM in my Meteor app. I have successfully added serialport and xbee-api. I can read xbee frames using console.log, but I cannot pass the frame to a Meteor method. The code below gives me an error about NPM functions and using bindEnvironment. I'm sure that it has something to do with Meteor running synchronous vs xbee-api running asynchronous. I'm fairly familiar with Meteor, but not with using it with NPM. I believe the answer may be in https://github.com/arunoda/meteor-npm. I don't really need a callback, as I just want the frame data passed to a method and I will handle it from there. Can anyone shed some light on this for me? Thanks in advance.
// Load serialport and xbee-api
var serialport = Meteor.require('serialport');
var SerialPort = serialport.SerialPort;
var xbee_api = Meteor.require('xbee-api');
// Load constants to help with remembering hex codes for xbees
var C = xbee_api.constants;
// Create xbee
var xbee = new xbee_api.XBeeAPI({
api_mode: 2
});
// Create serial port
var serialPort = new SerialPort('/dev/tty.usbserial-A901L66E', {
baudrate: 9600,
// Provided with xbee-api. Could use com.parsers.raw and feed that to xbee-api
parser: xbee.rawParser()
});
// Setup action to take when serial port is connected
serialPort.on('open',function() {
console.log('Port open');
});
// Setup action to take when xbee packet is received
// frame_object is emitted by the xbee.rawParser every time a complete xbee packets is received
xbee.on('frame_object', function(frame) {
//Send frame to Meteor method
Meteor.call('xbeeIncoming', frame);
//console.log('>>',frame);
});
Meteor method definition:
Meteor.methods({
xbeeIncoming: function xbeeIncoming(frame) {
console.log('xbeeData');
//var xbeeSenderAddr = frame.addr
}
});
Why are you using a method to do this. If both of them are on the server side you could use a private method instead i.e
xbeeIncoming = function(frame) {
console.log('xbeeData');
}
instead of Meteor.call('xbeeIncoming', frame); you could use xbeeIncoming(frame);
You will need to wrap the callback from xbee in a bindEnvironment (provide it can be serialized into JSON/EJSON):
var onFrame = function(frame ) {
Meteor.call('xbeeIncoming', frame);
//console.log('>>',frame);
}
xbee.on('frame_object', Meteor.bindEnvironment(onFrame));
From within this, Meteor.call should work as expected

Resources