forked from firepick1/FireFuse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
firefuse.h
401 lines (354 loc) · 16.4 KB
/
firefuse.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
#ifndef FIREFUSE_HPP
#define FIREFUSE_HPP
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////// C DECLARATIONS ////////////////////////////////
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <FireLog.h>
#define MAX_GCODE_LEN 255 /* maximum characters in a gcode instruction */
#define STATUS_PATH "/status"
#define HOLES_PATH "/holes"
#define FIRESTEP_PATH "/firestep"
#define FIRELOG_PATH "/firelog"
#define CONFIG_PATH "/config.json"
#define ECHO_PATH "/echo"
// FireREST JSON network response sizes are obtained from FUSE file size.
// We provide a minimum size for sync requests that don't know actual response size in cve_getattr()
// Large values waste bandwidth, small values run the risk of clipping the returned JSON.
// To match the minimum size constraint, JSON text is padded with trailing spaces
#define MIN_SAVE_SIZE ((size_t) 256)
#define MIN_PROCESS_SIZE ((size_t) 2048)
#ifndef bool
#define bool int
#define TRUE 1
#define FALSE 0
#endif
typedef struct {
char *pData;
int length;
long reserved;
} FuseDataBuffer;
extern const char * fuse_root;
extern FuseDataBuffer headcam_image; // perpetually changing image
extern FuseDataBuffer headcam_image_fstat; // image at time of most recent fstat()
extern FuseDataBuffer* firefuse_allocImage(const char *path, int *pResult);
extern FuseDataBuffer* firefuse_allocDataBuffer(const char *path, int *pResult, const char *pData, size_t length);
bool firefuse_isFile(const char *value, const char * suffix);
extern void firefuse_freeDataBuffer(const char *path, struct fuse_file_info *fi);
extern const char* firepick_status();
extern const void* firepick_holes(FuseDataBuffer *pJPG);
extern int background_worker();
extern bool is_cv_path(const char * path);
extern bool is_cnc_path(const char *path);
int firefuse_getattr_file(const char *path, struct stat *stbuf, size_t length, int perm);
int firefuse_getattr(const char *path, struct stat *stbuf);
int firefuse_open(const char *path, struct fuse_file_info *fi);
int firefuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int firefuse_write(const char *path, const char *buf, size_t bufsize, off_t offset, struct fuse_file_info *fi);
int firefuse_release(const char *path, struct fuse_file_info *fi);
int firefuse_main(int argc, char *argv[]);
int firerest_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi);
int firerest_getattr_default(const char *path, struct stat *stbuf);
char * firerest_config(const char *path);
static inline int firefuse_readBuffer(char *pDst, const char *pSrc, size_t size, off_t offset, size_t len) {
size_t sizeOut = size;
if (offset < len) {
if (offset + sizeOut > len) {
sizeOut = len - offset;
}
memcpy(pDst, pSrc + offset, sizeOut);
} else {
sizeOut = 0;
}
return sizeOut;
}
#define FIREREST_1 "/1"
#define FIREREST_GRAY "/gray"
#define FIREREST_BGR "/bgr"
#define FIREREST_CAMERA_JPG "/camera.jpg"
#define FIREREST_CAMERA_JPG_TILDE "/camera.jpg~"
#define FIREREST_CV "/cv"
#define FIREREST_SYNC "/sync"
#define FIREREST_CVE "/cve"
#define FIREREST_CNC "/cnc"
#define FIREREST_FIRESIGHT_JSON "/firesight.json"
#define FIREREST_PROPERTIES_JSON "/properties.json"
#define FIREREST_MONITOR_JPG "/monitor.jpg"
#define FIREREST_OUTPUT_JPG "/output.jpg"
#define FIREREST_PROCESS_FIRE "/process.fire"
#define FIREREST_GCODE_FIRE "/gcode.fire"
#define FIREREST_SAVED_PNG "/saved.png"
#define FIREREST_SAVE_FIRE "/save.fire"
#define FIREREST_VAR "/var/firefuse"
bool cve_isPathSuffix(const char *path, const char *suffix);
int cve_save(FuseDataBuffer *pBuffer, const char *path);
int cve_getattr(const char *path, struct stat *stbuf);
int cve_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi);
int cve_open(const char *path, struct fuse_file_info *fi);
int cve_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int cve_write(const char *path, const char *buf, size_t bufsize, off_t offset, struct fuse_file_info *fi);
int cve_release(const char *path, struct fuse_file_info *fi);
int cve_truncate(const char *path, off_t size);
int cve_rename(const char *path1, const char * path2);
int cnc_getattr(const char *path, struct stat *stbuf);
int cnc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi);
int cnc_open(const char *path, struct fuse_file_info *fi);
int cnc_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int cnc_write(const char *path, const char *buf, size_t bufsize, off_t offset, struct fuse_file_info *fi);
int cnc_release(const char *path, struct fuse_file_info *fi);
int cnc_truncate(const char *path, off_t size);
inline bool verifyOpenR_(const char *path, struct fuse_file_info *fi, int *pResult) {
switch (fi->flags & 3) {
case O_RDONLY:
LOGTRACE1("verifyOpenR_(%s) O_RDONLY", path);
break;
case O_WRONLY:
case O_RDWR:
default:
LOGERROR2("verifyOpenR_(%s) EACCESS %o", path, fi->flags);
(*pResult) = -EACCES;
break;
}
return (*pResult) == 0;
}
inline bool verifyOpenRW(const char *path, struct fuse_file_info *fi, int *pResult) {
if ((fi->flags & O_DIRECTORY)) {
LOGERROR2("verifyOpenRW(%s) DIRECTORY EACCESS %o", path, fi->flags);
(*pResult) = -EACCES;
} else {
switch (fi->flags & 3) {
case O_RDONLY:
LOGTRACE1("verifyOpenRW(%s) O_RDONLY", path);
break;
case O_WRONLY:
LOGTRACE1("verifyOpenRW(%s) O_WRONLY", path);
break;
case O_RDWR: // Simultaneous read/write not allowed
LOGERROR2("verifyOpenRW(%s) EACCESS %o", path, fi->flags);
(*pResult) = -EACCES;
break;
default:
LOGERROR2("verifyOpenRW(%s) UNKNOWN EACCESS %o", path, fi->flags);
(*pResult) = -EACCES;
break;
}
}
return (*pResult) == 0;
}
int firestep_init();
void firestep_destroy();
int firestep_write(const char *buf, size_t bufsize);
const char * firestep_json();
int tinyg_hash(const char *value, size_t len);
#ifdef __cplusplus
//////////////////////////////// C++ DECLARATIONS ///////////////////////////////////////////////////
} // __cplusplus
#include "LIFOCache.hpp"
#include <vector>
#include <map>
#include <string.h>
#include <signal.h>
#include "FireUtils.hpp"
extern int cameraWidth; // config.json provided camera width
extern int cameraHeight; // config.json provided camera height
extern string cameraSourceName; // config.json provided camera source name
extern string cameraSourceConfig; // config.json provided camera souce config
void cve_process(const char *path, int *pResult);
class BackgroundWorker;
// firerest.cpp
string hexFromRFC4648(const char *rfc);
string hexToRFC4648(const char *hex);
// background.cpp
SmartPointer<char> loadFile(const char *path, int suffixBytes=0); //Return allocated memory with contents
// ****************************************************************************
// cv.cpp - Implementation of Computer Vision Endpoint (https://github.com/firepick1/FireREST/wiki/FireREST-CV)
// There will be one CVE element for each endpoint in /dev/firefuse.
typedef class CVE {
private: string name; //
private: bool _isColor; // TRUE if CVE is a color endpoint, or FALSE if endpoint is grayscale
public: LIFOCache<SmartPointer<char> > src_saved_png; // Pointer to https://github.com/firepick1/FireREST/wiki/saved.png
public: LIFOCache<SmartPointer<char> > src_save_fire; // Pointer to https://github.com/firepick1/FireREST/wiki/save.fire (grab saved.png when accessed)
public: LIFOCache<SmartPointer<char> > src_process_fire; // Pointer to https://github.com/firepick1/FireREST/wiki/process.fire
public: LIFOCache<SmartPointer<char> > src_firesight_json; // Pointer to https://github.com/firepick1/FireREST/wiki/firesight.json
public: LIFOCache<SmartPointer<char> > src_properties_json; // Pointer to https://github.com/firepick1/FireREST/wiki/properties.json
public: static string cve_path(const char *pPath); // String containing path to Computer Vision Endpoint
public: CVE(string name); // Constructor
public: ~CVE(); // Destructor
public: inline string getName() { return name; }
public: int save(BackgroundWorker *pWorker);
public: int process(BackgroundWorker *pWorker);
public: inline bool isColor() { return _isColor; } // TRUE if CVE is a color endpoint, or FALSE if endpoint is grayscale
} CVE, *CVEPtr;
// ****************************************************************************
// cnc.cpp - Implementation of Device Control Endpoint (https://github.com/firepick1/FireREST/wiki/FireREST-CNC)
typedef class DCE {
private: string name;
private: int serial_fd;
private: bool is_sync;
private: string serial_path;
private: string serial_stty;
private: pthread_t tidReader;
public: vector<string> serial_device_config;
private: char *jsonBuf;
private: int activeRequests;
private: int jsonLen;
private: int jsonDepth;
private: char *inbuf;
private: int inbuflen;
private: int inbufEmptyLine;
private: int serial_send_eol(const char *buf, size_t bufsize);
private: int serial_send(const char *data, size_t length);
private: int serial_read_char(int c);
private: int update_serial_response(const char *serial_data);
private: static void * serial_reader(void *arg);
private: const char * read_json();
protected: virtual void send(string request, json_t*response);
// Common data
public: LIFOCache<SmartPointer<char> > snk_gcode_fire;
public: LIFOCache<SmartPointer<char> > src_gcode_fire;
//public: LIFOCache<SmartPointer<char> > src_properties_json;
public: static vector<std::string> gcode_lines(const string &gcode);
public: static string dce_path(const char *pPath);
public: DCE(string name);
public: ~DCE();
public: void clear();
public: bool isSync() { return is_sync; }
public: int serial_init();
public: inline string getName() { return name; }
public: int gcode(BackgroundWorker *pWorker);
public: inline string getSerialStty() { return serial_stty; }
public: inline void setSerialStty(const char * value) { serial_stty = value; }
public: inline string getSerialPath() { return serial_path; }
public: inline void setSerialPath(const char * value) { serial_path = value; }
public: inline vector<string> getSerialDeviceConfig() { return serial_device_config; }
} DCE, *DCEPtr;
// ****************************************************************************
// background.cpp - Gets called whenever cve_open() is called.
// During cve_open (cv.cpp), worker.cameras[] will be populated with a CameraNode object for each camera present.
typedef class CameraNode {
private: double camera_throttle_seconds; // prevent camera abuse
private: double camera_seconds; // time of last camera update
private: double output_seconds; // time of last FireSight pipeline completion
private: double monitor_duration; // number of seconds to show last output
private: pid_t raspistillPID;
// Common data
public: LIFOCache<SmartPointer<char> > src_camera_jpg;
public: LIFOCache<Mat> src_camera_mat_gray;
public: LIFOCache<Mat> src_camera_mat_bgr;
public: LIFOCache<SmartPointer<char> > src_monitor_jpg;
public: LIFOCache<SmartPointer<char> > src_output_jpg;
// For BackgroundWorker use
public: CameraNode();
public: ~CameraNode();
public: void init(); //Inits camera. Starts Raspistill, etc..
public: void clear();
public: int async_update_camera_jpg(); //
public: int update_camera_jpg(SmartPointer<char> jpg);
public: int async_update_monitor_jpg();
public: void setOutput(Mat image);
} CameraNode;
#define MAX_CAMERAS 1 /* TODO: Make code actually work for multiple cameras */
// ****************************************************************************
// background.cpp - singleton class
typedef class BackgroundWorker {
private: double idle_period; // minimum seconds between idle() execution. Gets set by config.json.
private: std::map<string, CVEPtr> cveMap;
private: std::map<string, DCEPtr> dceMap;
private: std::map<string, DCEPtr> serialMap;
private: double idle_seconds; // time of last idle() execution
private: int async_save_fire();
private: int async_process_fire();
private: int async_gcode_fire();
public: CameraNode cameras[MAX_CAMERAS];
public: static double seconds();
public: BackgroundWorker();
public: ~BackgroundWorker();
public: static int callSystem(char *cmdbuf); //Execute a system shell command
public: CVE& cve(string path, bool create=FALSE);
public: DCE& dce(string path, bool create=FALSE);
public: vector<string> getCveNames();
public: vector<string> getDceNames();
public: void clear();
public: void process();
public: inline void setIdlePeriod(double value) { idle_period = value; }
public: inline double getIdlePeriod() { return idle_period; }
public: inline DCEPtr getSerialDCE(string serialPath) { return serialMap[serialPath]; }
public: inline void setSerialDCE(string serialPath, DCEPtr pDce) { serialMap[serialPath] = pDce; }
// TESTING ONLY
public: void processInit();
public: int processLoop();
public: void idle();
} BackgroundWorker;
extern BackgroundWorker worker; // BackgroundWorker singleton background worker
// ****************************************************************************
// firerest.cpp
typedef class JSONFileSystem {
private: std::map<string, json_t *> dirMap;
private: std::map<string, json_t *> fileMap;
private: json_t *resolve_file(const char *path);
public: JSONFileSystem();
public: ~JSONFileSystem();
public: static vector<string> splitPath(const char *path);
public: void clear();
public: json_t *get(const char *path);
public: void create_file(const char *path, int perm);
public: inline void create_file(string path, int perm) { create_file(path.c_str(), perm); }
public: vector<string> fileNames(const char *path);
public: bool isFile(const char *path);
public: bool isDirectory(const char *path);
public: int perms(const char *path);
} JSONFileSystem;
// ****************************************************************************
// firerest.cpp - read/write/modify of config.json (shared with FireREST et. al.)
typedef class FireREST {
private: pthread_mutex_t processMutex;
private: int processCount;
private: JSONFileSystem files;
private: string config_camera(const char* cv_path, json_t *pCamera, const char *pCameraName, json_t *pCveMap);
private: string config_cv(const char* root_path, json_t *pConfig);
private: string config_cnc(const char* root_path, json_t *pConfig);
private: string config_cnc_serial(string dcePath, json_t *pSerial);
private: string config_dce(string dcePath, json_t *pConfig);
private: void create_resource(string path, int perm);
public: FireREST();
public: ~FireREST();
public: int incrementProcessCount();
public: int decrementProcessCount();
public: char * configure_path(const char *path);
public: void configure_json(const char *pJson);
public: int perms(const char *path) { return files.perms(path); }
public: bool isDirectory(const char *path) { return files.isDirectory(path); }
public: bool isFile(const char *path) { return files.isFile(path); }
public: static bool isSync(const char *path);
public: vector<string> fileNames(const char *path) { return files.fileNames(path); }
} FireREST;
extern FireREST firerest;
// ****************************************************************************
// Calibrate.cpp
typedef class SpiralIterator { // simpler than a C++ <iterator>
private: int x;
private: int y;
private: int mx;
private: int my;
private: int dx;
private: int dy;
private: int state;
private: int xMax;
private: int yMax;
private: float xScale;
private: float yScale;
private: float xOffset;
private: float yOffset;
private: void reset();
public: SpiralIterator(int xSteps=21, int ySteps=0);
public: inline void setScale(float xScale, float yScale) { this->xScale = xScale; this->yScale = yScale; }
public: inline void setOffset(float xOffset, float yOffset) { this->xOffset = xOffset; this->yOffset = yOffset; }
public: inline float getX() { return x*xScale + xOffset; }
public: inline float getY() { return y*yScale + yOffset; }
public: bool next();
} SpiralIterator;
#endif // __cplusplus
//////////////////////////////////// FIREFUSE_H ////////////////////////////////////////////////////////
#endif // FIREFUSE_HPP