/* This file just lists some ideas for the future... I'll keep it for now. */ /* Configuration */ #define CFG_BUF_SIZE 4096 #define CFG_MAX_ITEMS 256 #define CFG_MAX_CALIBS 16 #include "ring_buf.h" #include "fd.h" /* Description of an item type. */ struct item_info { /* 32-bit globally-recognized product identifier. */ long id; /* Self-explanatory. */ char* name; /* I suppose this acts as a placeholder for more structured information. * Actually expanding this to a full struct is a project in itself. */ char* description; /* Typical mass of the container. Before calculating volume, this is * subtracted from the item's mass. */ int container_mass; /* Grams per liter. */ double density; /* More ideas: * * - Substitution information, something along the lines of "a Persian lime * counts as two and a half Key limes." Or maybe "Ro-Tel consists of * diced green chilis and tomatos." * * - Nutrition facts, including serving size. * * - Unit information. Different kinds of foods are conventionally * measured in different ways. For now just use liters. * * - Cross-reference with recipe list. This would only be a speed * optimization, I think. * * - Quantity on-hand. Again, an optimization. * * - Price and other purchase information. In the future it might be kind * of neat for Smartshelf to generate shopping lists and maybe even * place orders for food to be delivered or picked up at a grocery store. * * - Typical initial mass and volume. This can be used to determine if the * box/jar has been opened yet and also to help identify bogus values. * * - Pictures for the GUI to display to help the user locate the item. * * - Shelf life before and after opening container. * * - Footprint. I'm not sure how this would be useful, but it's an idea. * * - User preferences inferred from history. As an example, Smartshelf can * observe that this food is consumed at a high rate, and therefore it'll * suggest that it be purchased in larger quantity. * * - Categorization information. For instance, a food can be marked as * salty, and if Smartshelf observes that the user doesn't much care for * the taste, then recipes can be adjusted, alternatives suggested, etc. * * - Much is possible... */ } item_info_t; /* Single item on a shelf. */ struct item { /* Product identifier, stored as the low 32 bits of the RFID tag. */ long id; /* The high 32 bits of the RFID tag. For now let's call it an expiration * date, format to be determined. Or maybe it should be the date of * production, if shelf life information is available. * * Gee, is it important that separate items of the same type have separate * tags? Yeah, I think so, since otherwise adding a new item of a type * already present on the shelf might cause it to not be counted. If * there are multiple tags with the same value, will the RFID reader * separately report all instances? When removing an item of which there * are several on the shelf, the specific item can be determined by * watching how much weight was lifted. * * Let's think about it some more... */ long expiration; /* Pointer to the corresponding item_info. This is an optimization to * avoid repeated lookups by id. If we store item_info objects in a * balanced tree and efficiency is good enough, this can be dropped. */ item_info_t* info; /* Estimated position on the shelf. These numbers can be multiplied by the * shelf's dimensions to get an actual physical location, but for now it's * not strictly necessary. */ struct {double x, y;} position; /* Estimated mass in grams. To get the volume in liters, subtract the * container's mass and then divide by the item's density. */ int mass; } item_t; /* A smart shelf! */ struct shelf { /* What's on the shelf?? */ item_t items[CFG_MAX_ITEMS]; int num_items; /* Maybe store the dimensions of the shelf. */ } shelf_t; /* List of serial ports. */ /* extern serial_t ports[2]; */ /* Evaluates to the lesser of the two operands. */ #define MIN(a, b) ({typeof(a) _a = (a); typeof(b) _b = (b); \ _a < _b ? _a : _b;}) /* Evaluates to the greater of the two operands. */ #define MAX(a, b) ({typeof(a) _a = (a); typeof(b) _b = (b); \ _a > _b ? _a : _b;}) /* Evaluates to the number of elements in an array. */ #define LEN(x) (sizeof(x) / sizeof(*(x))) /* Connection to a client monitoring the hardware. * * Okay, so what's the division of responsibility between this program and the * client? At the moment I think it would be best to make this program very * powerful and keep the client lightweight. All the databases and artificial * intelligence should stay here, and the client's main responsibility is * interfacing with the user. */ typedef struct client { FD_STRUCT; /* Inherit parent struct's fields. */ int for_xmit; /* True if connected to stdout. */ int for_recv; /* True if connected to stdin. */ /* Probably more stuff goes here... */ } client_t; /* State information for a Texas Instruments RFID tag reader. */ typedef struct rfid_reader { long long tags[CFG_MAX_ITEMS]; /* List of tags. */ int num_tags; /* Number of tags in reader's range. */ int packet_rem; /* Bytes remaining until end of packet. */ shelf_t* shelf; /* Associated shelf. */ } rfid_reader_t; /* State information for a pressure sensor device. The current pressure sensor * consists of four physical sensors and two magnetic reed switches. */ typedef struct pressure { struct calib { /* A calibration sample. */ int val; /* Value read from sensor. */ float mass; /* Mass placed on that sensor. */ } calibs[CFG_MAX_CALIBS][4]; /* List of samples, for each sensor. */ int num_calibs; /* Number of calibration samples. */ int door_status; /* True if the door is opened. */ int have_sync; /* Currently in sync with device? */ int packet_rem; /* Bytes remaining until end of packet. */ int packet_len; /* Number of bytes in a good packet. */ int packet_bad; /* If true, current packet is bad. */ shelf_t* shelf; /* Associated shelf. */ } pressure_t; /* vim: set syn=c: */