Revert converted strings to their original representation
1. The naming should follow a similar pattern as the compatible image sets.
2. The original emoji are used as fallback.
Requirements
Xcode 11
iOS 13.0+
Lower versions haven’t been tested, although the framework may run without
issues on a lower version.
Swift 5
Using the framework in an Objective-C project may require some
modifications to the source. Support for Objective-C will possibly be
added at some point in the future.
Open your project use Xcode.
Click File -> Add Packages, enter repository url.
https://github.com/xoudini/emojica
Manual installation
Clone the repository, and drag Emojica.xcodeproj into your project
hierarchy in Xcode.
Select your project, then select your application’s target under Targets.
Under the General tab, click the + under Embedded Binaries.
Select Emojica.frameworkiOS and finish by pressing Add.
If Xcode gives you a No such module 'Emojica' compiler error at your
import statement, just build your application (or the framework) once. Also,
each time you Clean (⇧⌘K) the project Xcode will give you the same error,
and the solution is the same.
Usage
import Emojica
Instantiation
letemojica=Emojica()
// Creates an instance with a font.
letemojica=Emojica(font:UIFont.systemFont(ofSize:17.0))
Configure instance
Set font:
emojica.font =UIFont.systemFont(ofSize:17.0)
If no font is set, the system font is used.
Set size:
emojica.pointSize =17.0
If you’re satisfied with the default font, you can just set the size.
The value for pointSize is 17.0 by default.
A value between 0 and 8 that sets the minimum width for code point strings in
order to correctly find the images for the custom emoji. The character 0 is
used for padding.
You can directly convert text input by implementing the UITextViewDelegate
method textViewDidChange(_:) and passing the changed UITextView to the
Emojica method by the same name:
The below image sets are tested, but other image sets may work just as well.
If you have an image set that should be added to Emojica, please create an
Issue.
NOTE: The newest EmojiOne and Noto sets haven’t been checked in a while.
1. U+2640, U+2642 and U+2695 and sequences containing these characters are
unsupported.
Example Project
The example EmojicaExample.xcodeproj is set up but does not contain
images. To test the project, add your emoji images to the Images group and
Run.
Preparations
WARNING: Running the script will overwrite the image names, so do
not run the script over a unique image set!
Some image sets may have to be slightly modified before usage. Check the table
in Compatible Image Sets if you’re using a set marked
Prepare, and if you are, follow these instructions:
1. Copy/move the contained file rename.sh into the folder containing your image set.
2. Open your preferred terminal.
3. Navigate into the directory:
$ cd /Path/To/Your/ImageSet/
4. Run the script:
$ sh rename.sh
Contact
Feedback and questions are welcome, create an
Issue for bugs, problems, and
potential feature requests.
If you end up using this framework in one of your projects, feel free to let me
know, e.g. on Twitter.
Contributions
The list of contributors to this project can be found
here.
If you would like to contribute, don’t hesitate to open an issue or a pull
request.
Revert converted strings to their original representation
1. The naming should follow a similar pattern as the compatible image sets.
2. The original emoji are used as fallback.
Requirements
Xcode 11
iOS 13.0+
Lower versions haven’t been tested, although the framework may run without
issues on a lower version.
Swift 5
Using the framework in an Objective-C project may require some
modifications to the source. Support for Objective-C will possibly be
added at some point in the future.
Open your project use Xcode.
Click File -> Add Packages, enter repository url.
https://github.com/xoudini/emojica
Manual installation
Clone the repository, and drag Emojica.xcodeproj into your project
hierarchy in Xcode.
Select your project, then select your application’s target under Targets.
Under the General tab, click the + under Embedded Binaries.
Select Emojica.frameworkiOS and finish by pressing Add.
If Xcode gives you a No such module 'Emojica' compiler error at your
import statement, just build your application (or the framework) once. Also,
each time you Clean (⇧⌘K) the project Xcode will give you the same error,
and the solution is the same.
Usage
import Emojica
Instantiation
letemojica=Emojica()
// Creates an instance with a font.
letemojica=Emojica(font:UIFont.systemFont(ofSize:17.0))
Configure instance
Set font:
emojica.font =UIFont.systemFont(ofSize:17.0)
If no font is set, the system font is used.
Set size:
emojica.pointSize =17.0
If you’re satisfied with the default font, you can just set the size.
The value for pointSize is 17.0 by default.
A value between 0 and 8 that sets the minimum width for code point strings in
order to correctly find the images for the custom emoji. The character 0 is
used for padding.
You can directly convert text input by implementing the UITextViewDelegate
method textViewDidChange(_:) and passing the changed UITextView to the
Emojica method by the same name:
The below image sets are tested, but other image sets may work just as well.
If you have an image set that should be added to Emojica, please create an
Issue.
NOTE: The newest EmojiOne and Noto sets haven’t been checked in a while.
1. U+2640, U+2642 and U+2695 and sequences containing these characters are
unsupported.
Example Project
The example EmojicaExample.xcodeproj is set up but does not contain
images. To test the project, add your emoji images to the Images group and
Run.
Preparations
WARNING: Running the script will overwrite the image names, so do
not run the script over a unique image set!
Some image sets may have to be slightly modified before usage. Check the table
in Compatible Image Sets if you’re using a set marked
Prepare, and if you are, follow these instructions:
1. Copy/move the contained file rename.sh into the folder containing your image set.
2. Open your preferred terminal.
3. Navigate into the directory:
$ cd /Path/To/Your/ImageSet/
4. Run the script:
$ sh rename.sh
Contact
Feedback and questions are welcome, create an
Issue for bugs, problems, and
potential feature requests.
If you end up using this framework in one of your projects, feel free to let me
know, e.g. on Twitter.
Contributions
The list of contributors to this project can be found
here.
If you would like to contribute, don’t hesitate to open an issue or a pull
request.
>>>>>DTMF BASED PASSWORD PROTECTED LOCK SYSTEM <<<<<
I had completed this project on 30 Sept. 2018 in 3rd Semester of B. Tech
I think this is unique type of lock you find on Internet or github because its not easy to make password based lock using DTMF
As we all know that we can control or automate things using our mobile keypad through DTMF Module.
So I designed a lock system which can locked and unlocked using a password entered through our mobile after connecting it to the module.
DTMF receives the key value pressed on mobile as a input in its four digital input pins which generates value in binary.
eg. If I press 1 on mobile then I receive 0 0 0 1 as four inputs in DTMF input pins.
The main problem with DTMF is that until I press a new key, it continuously reads or repeats previous key input.
means if previously I pressed 1 then it continuously shows 0 0 0 1 as input or sensing value until we press another key.
This continuous flow was the main problem in making password based lock.
I tried to break this continuous flow by using some programming techniques.
HOW TO USE**
I impleaments the code for 4 digit long password but you can increase its length according to your need.
Attention:
Before start entering password you have press #.
Then enter your 4 digits password.
Then press * at the end.
This # indicates that I am start entering my password
and * indicates that I successfully entered my password.
this indications helps in dealing with continuous flow inputs.
Foster care for your python projects. This tool is a simple way to build and publish your packages to PyPI, making them available for a pip install.
Quickstart
Install foster:
pip install foster
Init your package settings:
foster init
This will create a package.py file in your current directory (this should be the root of your project).
This is the only file you need to commit to your version control (git).
Edit the file with your package information. Example:
name='myproject'version='0.0.0'packages= ['myproject', 'myproject.subpackage']
files= ['myproject/files', 'LICENSE']
requirements= ['Jinja2 >= 2, < 3']
scripts= ['myp=myproject.command:run']
author= 'JohnDoeauthor_email='john.doe@gmail.com'license='MIT'url='https://github.com/...'keywords='myproject awesome python'description='Lorem ipsum dolor sit amet, consectetur adipisicing elit'long_description="""Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod temporincididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrudexercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."""
In the above example, the package will:
Include the python packages myproject and myproject.subpackage
Include all the files in the myproject/files directory (recursively) and the LICENSE file
Add Jinja2 (version 2.x.x) as a requirement (it’s probably not a good idea to pinpoint the version, but you can)
Add the console script myp, making it execute the run callable in the myproject.command file
If you’re not using some of the fields, like files or scripts for instance, just leave them empty (don’t delete them).
Next, build your package (this will create a dist directory):
foster build
Finally, publish your package to the PyPI test environment:
foster publish staging
Change staging for production when you’re ready for the real deal.
Packages uploaded to the PyPI’s test environment can be tested with:
Simple Python scripts to turn a WLED device on/off with sunset/sunrise.
There are two scripts in the project:
sunset_sunrise_startup.py
Designed to run when you turn your computer on.
Uses date, longitude and latitude to calculate sunset and sunrise times (thanks to Suntime).
Turns on LEDs when sun has set.
Turns off LEDs when sun has risen.
sunset_sunrise_shutdown.py
Designed to run when you turn your computer off.
Turns off LEDs (if already on).
These scripts will ensure that the LEDs will only be on when your computer is turned on and when it is dark outside.
A similar effect can be achieved with Home Assistant and Alexa routines but I prefer this solution as there is no need for another IoT device to be constantly running.
Getting Started
These instructions will get you a copy of the project up and running on your local machine.
Prerequisites
To get the script running, all you will need to have is:
Python (3.3+)
Windows 10
Device running WLED on your network
Installation
Clone the repo and enter the folder
git clone https://github.com/benostein/SunsetSunriseWLED.git
cd SunsetSunriseWLED
Create virtual environment
py -m venv env
Activate virtual environment
.\env\Scripts\activate
This can be verified by using the command which python and checking it is using the Python interpreter in the env folder.
Install the Python libraries
pip install -r requirements.txt
Edit config.py
# Your latitude hereLATITUDE=51.5074# Your longitude hereLONGITUDE=0.1278# Your WLED IP address hereLED_IP_ADDRESS="192.168.0.57"# Config sleep delay here (optional)SLEEP_DELAY=2
Run generate_bat_files.py
py generate_bat_files.py
This will generate two .bat files that will launch the Python scripts.
Run gpedit.msc (Local Policies)
Computer Configuration -> Windows Settings -> Scripts -> Startup -> Properties -> Add -> (select path of led_startup.bat)
Computer Configuration -> Windows Settings -> Scripts -> Shutdown -> Properties -> Add -> (select path of led_shutdown.bat)
These scripts will now run automatically, so you should not have to worry about turning your LEDs on or off again.
Vim plugin for showing all your <Leader> mappings in a readable table including the descriptions.
Installation
Copy plugin/follow-my-lead.vim to ~/.vim/plugin
Or add a GitHub repository entry if you are using a Plugin Manager such as Vundle:
Plugin'ktonga/vim-follow-my-lead'
Features
List <Leader> mappings defined by the user and the plugins
By default only mappings defined in .vimrc are listed. It honours $MYVIMRC variable
Mappings from all scripts sourced by Vim can be listed if specified by configuration (see Options)
If the line previous to the mapping is a comment it will be used as the description
If no comment is available the rhs of the mapping is used as description
Mappings are shown in a table, grouped by source, with the following columns
Mode: which mode the mapping applies to
LHS: left hand side of the mapping (without <Leader>)
Description: The mapping comment if present. The rhs otherwise
Screenshots
Shortcuts
<Leader>fml: Default mapping for triggering the plugin. It shows the mapping in a new window
q: Closes the mappings window
Options
g:fml_all_sources: if 1 all sources are used, if 0 just $MYVIMRC is used. Default 0
More options coming soon
License
Copyright (C) 2015 Gaston Tonietti
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This is a Springboot application to run with MariaDB as Database accessed via JPA, enabled REST access. As package manager Maven is used.
It runs with Java OpenJDK 8 to 11.
Time to setup: (depending on linux experience level) 5 to 20 mins.
ChangeLog:
v0.1.5 (in progress)
added react-router to take care of multi pages
implemented historical inverter data for yearly/monthly usage and averages
added settings page to view/change general settings
v0.1.4
added chart to visualize current energy input and output
using scss to generate style
improve responsive design especially for small screens
added logging of charging data
v0.1.3
added powerchart to visualize total metering data (produced vs consumed)
visualized status for metering data in energychart (green line/circles on not full data)
fixed error on bad charger response data
added bootstrap and responsive layout
v0.1.2
smart charging including evaluation every rough/5-min data
added react frontend with basic charger overview and settings
added d3 energy chart for inverter overview incl. consumption and production data
additional settings check and setup on startup of app
v0.1.1
inverter repository and service to access basic inverter data
charger repository and service to access basic charger data
scheduler for detail/rough/daily inverter data summaries
setting repository and service to access basic setting data
Installation
pack as jar with: mvn install
and run with (on f.e. a raspberry pie 3) or automatic as a service like described below:
use a current java version f.e., or because of non compliant to ARMv7+ VFP use jre 8 for a raspberry 1:
be patient with a pi 1 though (test took 390 seconds to start SmarticsApplication – versus 56 secs on a pi 3)!
sudo mariadb
create user smartics identified by ‘smartics’;
create database smartics;
additionally grant access by user and locally:
the same can be added by replacing ‘localhost’ with the ip of the remote system of choice for remote db access.
GRANT USAGE ON . TO ‘smartics’@localhost IDENTIFIED BY ‘smartics’;
GRANT ALL privileges ON smartics.* TO ‘smartics’@localhost;
FLUSH PRIVILEGES;
quit
sudo service mariadb restart
sudo mariadb -u smartics -p
run automatic on startup
sudo nano /etc/rsyslog.d/smartics.conf
if $programname == ‘smartics’ then /var/log/smartics-0.1.log
if $programname == ‘smartics’ and $msg contains ‘ERROR’ then /var/log/smartics-0.1-error.log
if $programname == ‘smartics’ then stop
charger: error on status-set leads to error in ChargerRepositoryImpl leading to killing of scheduler!!
inverterarchiverecalc produces daily summary, leading to 416/missing data if done for today (won’t override at end of day)
inverterarchiverecalc produces rough/min entry for current time that won’t be overridden in next run (rough already ran)
~ energyChart: consumption can be more: 7,000 Wh – paint extrem values extra?
energyChart: production values over night are 0 – skip rect for those values! (do not add to array)
archive data: correct 1st entry min of day not gotten and visualization in consumed-graph/path
todos
fix liquibase (add correctly to project, generate diff)
New developments will be done in extra branches and will be tested before merging in the developtment branch, so the developmet version should usually be usable (consider it in a beta stage), while feature branches should be considered alpha.
Status master development branch
GH Action
Windows users: the package contains c++ code, so if you compile yourself, you need RTools installed.
Older releases
To install a specific (older) release or a branch, decide for the version number / branch that you want to install in https://github.com/florianhartig/BayesianTools/releases (version numbering corresponds to CRAN, but there may be smaller releases that were not pushed to CRAN) and run, e.g.
with v0.0.10 replaced by the appropriate version number or branch.
Getting help
We highly welcome questions by users, so don’t be shy – any questions, even if it feels “stupid”, helps us to understand how we can improve the interface, documentation, or code of the package.
If you want to ask a question or report a bug, the most convenient way for us would be to provide a reproducible example via the GitHub issues
Support the minimum size/maximum size setting of the scroll bar.
Automatically hide the scroll bar and optional set the automatic hide delay.
Floating scroll bar (when the scroll container exceeds the visible area of the screen, the scroll bar is fixed at the bottom of the screen).
High performance.Optional debounce/throttle to observe size changes.。
Support native scroll mode (default) and simulate scroll mode (useful in scenes such as: scroll synchronously with outer float elements).
it’s lightweight. 16.5kb uncompressed, 4.5kb after compression (gzip).
typescript support.
Why I write this lib
I need a scrollbar that doesn’t change the native scrolling mechanism to easily integrate with other components. Yes, I am referring to the better-scroll’s transform simulation mechanism.
I need to satisfy the above requirement of a floating scrollbar, which is not available in other scrollbar components in the community.
I need a toggleable simulate scroll mode to synchronize the scrolling progress of the floating outer elements without delay. This can be satisfied by perfect-scrollbar, but it is too old, too heavy, too poor performance, and only supports simulated scrolling mode (under normal circumstances with native scroll mode performance is better, and touchpad sliding experience is more friendly).
I need the interaction detail that the mouse gets bigger when it is close to the scrollbar to facilitate clicking. This is also available in perfect-scrollbar, but other better libraries such as react-scrollbars-custom don’t support it.
I need a scrollbar that is as close to native as possible, 0-intrusive, and lightweight. Other scrollbars in the community like to add some extra concepts, which makes me uncomfortable.
I need a custom scrollbar with less performance drag. So: no excessive calculations at the js level, render method optimized as much as possible, css contain property would also help a lot. When I’m done with this and comparing the performance performance of other libraries in the community on an old machine, I confirm that custom-vue-scrollbar will outperform them all.
In addition to the following component Props, all native DOM properties and events can also be used.
class:string = undefined
Container class, which is generally only used to set the size.
style:object = undefined
Container style.
wrapperClass:string = undefined
Wrapper class, the place to set display, padding, etc.
wrapperStyle:object = undefined
Wrapper style.
contentClass:string = undefined
Content class, the place to set display, padding, etc.
contentStyle:object = undefined
Content style.
direction:'horizontal' | 'vertical' = ‘vertical’
If you need to change the content container to horizontal layout, you can set the component property ‘direction’ to ‘horizontal’ to change the layout to ‘display’: ‘flex’ & ‘flex-direction’: ‘row’. Or set it manually via ‘contentClass”https://github.com/”contentStyle’ properties. However, it is not recommended to set it manually, as the ‘direction’ property is related to the ‘fixedThumb’ property below.
thumbMinSize / thumbMaxSize:number = 48 / Infinity
Sets the minimum/maximum size of the scrollbar.
thumbWidth:number = 12
Set the width of the scrollbar thumb.
autoHide:boolean = true
When turned on, the scrollbar will be displayed only when the mouse hovers over the scroll container.
autoHideDelay:number(ms) = 900
When the scrolling is triggered, the scrollbar will be hidden only after the delay set by autoHideDelay.
autoExpand:boolean = true
Scroll bar default is 8px wide, the actual external has a 12px placeholder container, click, drag and drop logic is hanging on this placeholder container (convenient to click, 8px visually comfortable but difficult). When this option is turned on, the occupancy container hover, the scrollbar width will change to the width of the occupancy container.
fixedThumb:boolean = false
The ‘direction’ property specifies the direction as the ‘major axis direction’. When the ‘fixedThumb’ property is turned on, if the secondary axis has a scrollbar and the major axis has a scroll container that is partially off-screen. The scrollbar of the secondary axis will float to the edge of the screen.
throttleType:'throttle' | 'debounce' | 'none' = ‘debounce’
ResizeObserver listens for changes in the size of the container/content DOM Node to update the size of the scrollbar. Most scenarios do not require a high refresh rate and using ‘debounce’ is sufficient in most scenarios.
throttleWait:number = 333
The time to trigger when the ‘throttleType’ attribute is not ‘none’.
simulateScroll:boolean = false
Use ‘wheel’ to simulate scrolling instead of native scrolling. Turn it on when you need to synchronize the scrolling progress with an external floating element to eliminate the jitter caused by native scrolling that is not in the same event loop when synchronizing.
wrapperResize:(rect: Rect) => void
Triggered when the size of the scroller container changes
contentResize:(rect: Rect) => void
Triggered when the size of the scroller content changes
Overwrite scrollbar style
// Modify the scrollbar size (placeholder container), the width of the scrollbar display before hover is 2/3 of the placeholder container, as follows, it is 12px..scrollbar__thumbPlaceholder--vertical{
width: 20px;}.scrollbar__thumbPlaceholder--horizontal{
height: 20px;}// Modify the scrollbar style..scrollbar__thumb{background-color: red;}
This is the repository for the Keyple Android Validation Demo application.
This demo is an open source project provided by the Calypso Networks Association implementing
the Eclipse Keyple SDK in a typical use case that can serve as a basis for building a ticketing
ecosystem based on contactless cards and/or NFC smartphones.
The code can be easily adapted to other cards, terminals and business logic.
It shows how to check if a card is authorized to enter a controlled area (entering the transport network with
a Season Pass and/or Multi-trip ticket), a validation event is added in the event log to be checked by the Keyple Demo Control application.
The contracts are loaded in the Calypso card with the Android application of the Keyple Reload Demo package.
The demo application was tested on the following terminals:
Famoco FX205 via the open source plugins Famoco (for SAM access) and Android NFC (for card access).
Coppernic C-One 2 via the open source plugin Coppernic.
The following terminals have also been tested but as they require non-open source libraries, they are not active by default (see Using proprietary plugins)
Bluebird EF501 via the proprietary plugin Bluebird.
Flowbird Axio 2 via the proprietary plugin Flowbird.
As all the exchanges made with the card are cryptographically secured by a security module (SAM), it is mandatory to install it in the terminal for the application to work properly.
Supported Card Types
This application supports two types of cards:
Calypso Cards
Standard Calypso cards that support secure sessions with SAM authentication. These cards can contain
multiple contracts (up to 4 depending on the product type: Basic=1, Light=2, Prime/Regular=4) and
use secure cryptographic operations.
Storage Cards
Simple storage cards that don’t require SAM authentication. These cards contain a single contract
and use basic read/write operations without cryptographic security.
Important Note: The Storage Card implementation in this demo is intentionally basic and does not
account for potential specific capabilities that different types of storage cards might offer, such
as dedicated counters for specific components, advanced memory management, or card-specific security
features. A production application would likely need to consider and implement these card-specific
capabilities based on the actual storage card technology being used.
Security Consideration: No security mechanisms have been implemented for Storage Cards in this
demonstration. In a production environment, developers should implement appropriate security
measures to protect data exchanges, for example by using signatures generated by a SAM or other
cryptographic security modules suitable for their specific use case and security requirements.
These demos are all based on a common library that defines elements such as constants and data structures implemented
for the logic of the ticketing application: Keyple Demo Common Library.
Please refer to the README
file of this library to discover these data structures. All enumerated types used across the three demo applications (Priority Codes, Version Numbers, etc.) are defined in this common library to ensure consistency and interoperability between the different components of the ticketing ecosystem.
Validation Procedure
Validation Use Case
This use case searches for the best candidate for validation from the existing contracts in the card.
The goal is to minimize the number of records read, and thus commands exchanged with the card, while being able to
quickly ascertain if the application has or not any valid contracts for validation.
If a contract record needs to be analysed and is found to be expired, then its priority value must be updated to ensure
that in a next operation (and until the contract is reloaded or replaced) time will not needlessly be wasted in reading
this contract.
If the contract has an associated counter (depending on the ContractTariff field value) its value shall be decreased by
the required amount for the operation and a new event will be added.
Steps:
Detection and Selection
Event Analysis
Best Contract Search
Update Counter
Add new event
Process for Calypso Cards
For this validation demo application, a simple example validation procedure has been implemented.
This procedure is implemented in the CalypsoCardRepository class.
Opening a Calypso secure session is mandatory for this procedure since we need to write a new event in the event log.
If no Calypso SAM is present, then the procedure will not execute and display an error.
This procedure’s main steps are as follows:
Detection and Selection
Detection Analysis:
If AID not found reject the card.
Selection Analysis:
If File Structure unknown reject the card.
Environment Analysis:
Open a Validation session (Calypso Secure Session) reading the environment record.
Unpack environment structure from the binary present in the environment record:
If EnvVersionNumber of the Environment structure is not the expected one (==VersionNumber.CURRENT_VERSION for the current version) reject the card.
If EnvEndDate points to a date in the past reject the card.
Event Analysis:
Read and unpack the last event record:
If EventVersionNumber is not the expected one (==VersionNumber.CURRENT_VERSION for the current version) reject the card.
If EventVersionNumber == VersionNumber.UNDEFINED, return empty card status.
Store the ContractPriority fields in a persistent object.
Best Contract Search:
Create a list of ContractPriority fields that are different from PriorityCode.FORBIDDEN and PriorityCode.EXPIRED.
If the list is empty go to END.
Order the list by ContractPriority Value in ascending order (lowest priority number = highest priority).
For each element in the list:
Read and unpack the contract record for the index being iterated.
If ContractVersionNumber is not the expected one (==VersionNumber.CURRENT_VERSION for the current version) reject the card.
If ContractAuthenticator is not 0 perform the verification of the value by using the PSO Verify Signature command of the SAM (TODO: implementation pending).
If ContractValidityEndDate points to a date in the past update the associated ContractPriority field present in the persistent object to PriorityCode.EXPIRED and move to the next element in the list
If the ContractTariff value for the contract read is PriorityCode.MULTI_TRIP or PriorityCode.STORED_VALUE:
Read and unpack the counter associated to the contract (1st counter for Contract #1 and so forth).
If the counter value is 0 update the associated ContractPriority field present in the persistent object to PriorityCode.EXPIRED and move to the next element in the list
If the counter value is > 0 && ContractTariff == PriorityCode.STORED_VALUE && CounterValue < ValidationAmount move to the next element in the list
If the ContractTariff value is PriorityCode.SEASON_PASS, store the contract validity end date.
Update Counter:
Decrement the counter value by the appropriate amount (1 if ContractTariff is PriorityCode.MULTI_TRIP, and the configured validation amount if ContractTariff is PriorityCode.STORED_VALUE).
EventDateStamp = Current Date converted to DateCompact
EventTimeStamp = Current Time converted to TimeCompact
EventLocation = value configured in the validator
EventContractUsed = index of the contract found during Best Contract Search
ContractPriority1 = Value of index 1 of ContractPriority persistent object
ContractPriority2 = Value of index 2 of ContractPriority persistent object
ContractPriority3 = Value of index 3 of ContractPriority persistent object
ContractPriority4 = Value of index 4 of ContractPriority persistent object
Pack the Event structure and update it in the event file
END: Close the session
Process for Storage Cards
For Storage Cards, a simplified validation procedure is implemented in the StorageCardRepository class.
Storage Cards do not require SAM authentication and use simple read/write operations. The procedure is similar but adapted for the simpler card structure:
Important Limitations: This implementation is a basic demonstration and does not leverage specific capabilities that various storage card types might offer. Production applications should be adapted to take advantage of card-specific features such as:
Dedicated counter management for different card components
Advanced memory organization and access patterns
Card-specific security features or encryption capabilities
Optimized read/write operations based on card technology
Security Notice: This demonstration does not implement any security mechanisms for Storage Cards. Production applications should implement appropriate security measures such as:
Data encryption and authentication
Signature verification using SAM or other security modules
Secure key management and exchange protocols
Protection against replay attacks and data tampering
The validation procedure steps are:
Detection and Selection:
Same as Calypso cards but without secure session requirements.
Environment and Event Analysis:
Read environment, event, and contract data in a single operation using block reads.
Perform the same version and date validations as Calypso cards.
Contract Validation:
Storage Cards have only one contract, so no “best contract search” is needed.
Validate the contract based on its ContractTariff value:
PriorityCode.MULTI_TRIP: Check counter value and decrement by 1.
PriorityCode.STORED_VALUE: Check sufficient value and decrement by validation amount.
PriorityCode.SEASON_PASS: Validate against contract end date.
PriorityCode.FORBIDDEN, PriorityCode.EXPIRED, PriorityCode.UNKNOWN: Reject the card.
Update Operations:
Update the contract data with new counter values.
Create and write a new validation event.
Close the transaction without secure session procedures.
Screens
Device selection (DeviceSelectionActivity): Allows you to indicate the type of device used, in order to use the associated plugin.
Initially, devices using proprietary plugins are grayed out.
Settings (SettingsActivity): Allows to set the settings of the validation procedure:
Location: Where the validation is taking place. The validation location will be written on the newly created event.
Battery Powered: Check button to set if the battery powered feature is enable or not.
Home (HomeActivity): Displayed only if the ‘battered powered’ feature is enabled. Allows to launch the card detection phase.
Reader (ReaderActivity): Initializes the Keyple plugin. At this point the user must present the card that he wishes to validate.
Initialize the Keyple plugin: start detection on NFC and SAM (if available) readers.
Prepare and defines the default selection requests to be processed when a card is inserted.
Listens to detected cards.
Launches the Validation Procedure when a card is detected.
Validation result screen (CardSummaryActivity):
If the validation is successful, display:
Location of the validation.
Date and hour of the validation.
Depending on the contract type:
Season Pass: End of validity.
MultiTrip Ticket: number of tickets left.
If the validation fails, display the reason.
Ticketing implementation
Below are the classes useful for implementing the ticketing layer:
TicketingService
ReaderRepository
ReaderActivity.CardReaderObserver
CalypsoCardRepository / StorageCardRepository
TicketingService
This service is the orchestrator of the ticketing process.
Mainly used to manage the lifecycle of the Keyple plugin.
This service is used to initialize the plugin and manage the card detection phase.
It is called on the different steps of the reader activity lifecycle:
onResume:
Initialize the plugin (Card and SAM readers…)
Get the ticketing session
Start NFC detection
onPause:
Stop NFC detection
onDestroy:
Clear the Keyple plugin (remove observers and unregister plugin)
It prepares and scheduled the selection scenario that will be sent to the card when a card is detected by setting
the AID(s) and the reader protocol(s) of the cards we want to detect and read.
Once a card is detected, the service processes the selection scenario by retrieving the current CalypsoCard or StorageCard object.
This object contains information about the card (serial number, card revision…)
Finally, this class is responsible for launching the validation procedure and returning its result.
ReaderRepository
This service is the interface between the business layer and the reader.
ReaderActivity.CardReaderObserver
This class is the reader observer and inherits from Keyple class CardReaderObserverSpi
It is invoked each time a new CardReaderEvent (CARD_INSERTED, CARD_MATCHED…) is launched by the Keyple plugin.
This reader is registered when the reader is registered and removed when the reader is unregistered.
CardRepository
This class contains the implementation of the “Validation” procedure.
Two implementations are provided:
CalypsoCardRepository: For Calypso cards with secure session support
StorageCardRepository: For simple storage cards without secure session requirements
Priority Codes
The application uses the following priority codes for contract management:
PriorityCode.SEASON_PASS: Season pass contract (highest priority)