def FromReadings(cls, uuid, readings, events, report_id=IOTileReading.InvalidReadingID,
                     selector=0xFFFF, streamer=0x100, sent_timestamp=0, received_time=None):
        lowest_id = IOTileReading.InvalidReadingID
        highest_id = IOTileReading.InvalidReadingID
        for item in itertools.chain(iter(readings), iter(events)):
            if item.reading_id == IOTileReading.InvalidReadingID:
                continue
            if lowest_id == IOTileReading.InvalidReadingID or item.reading_id < lowest_id:
                lowest_id = item.reading_id
            if highest_id == IOTileReading.InvalidReadingID or item.reading_id > highest_id:
                highest_id = item.reading_id
        reading_list = [x.asdict() for x in readings]
        event_list = [x.asdict() for x in events]
        report_dict = {
            "format": cls.FORMAT_TAG,
            "device": uuid,
            "streamer_index": streamer,
            "streamer_selector": selector,
            "incremental_id": report_id,
            "lowest_id": lowest_id,
            "highest_id": highest_id,
            "device_sent_timestamp": sent_timestamp,
            "events": event_list,
            "data": reading_list
        }
        encoded = msgpack.packb(report_dict, default=_encode_datetime, use_bin_type=True)
        return FlexibleDictionaryReport(encoded, signed=False, encrypted=False, received_time=received_time)