Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-building-friend-networks-django-10
Packt
14 Oct 2009
6 min read
Save for later

Building Friend Networks with Django 1.0

Packt
14 Oct 2009
6 min read
An important aspect of socializing in our application is letting users to maintain their friend lists and browse through the bookmarks of their friends. So, in this section we will build a data model to maintain user relationships, and then program two views to enable users to manage their friends and browse their friends' bookmarks. Creating the friendship data model Let's start with the data model for the friends feature. When a user adds another user as a friend, we need to maintain both users in one object. Therefore, the Friendship data model will consist of two references to the User objects involved in the friendship. Create this model by opening the bookmarks/models.py file and inserting the following code in it: class Friendship(models.Model): from_friend = models.ForeignKey( User, related_name='friend_set' ) to_friend = models.ForeignKey( User, related_name='to_friend_set' ) def __unicode__(self): return u'%s, %s' % ( self.from_friend.username, self.to_friend.username ) class Meta: unique_together = (('to_friend', 'from_friend'), ) The Friendship data model starts with defining two fields that are User objects: from_friend and to_friend. from_friend is the user who added to_friend as a friend. As you can see, we passed a keyword argument called related_name to both the fields. The reason for this is that both fields are foreign keys that refer back to the User data model. This will cause Django to try to create two attributes called friendship_set in each User object, which would result in a name conflict. To avoid this problem, we provide a specific name for each attribute. Consequently, each User object will contain two new attributes: user.friend_set, which contains the friends of this user and user.to_friend_set, which contains the users who added this user as a friend. Throughout this article, we will only use the friend_set attribute, but the other one is there in case you need it . Next, we defined a __unicode__ method in our data model. This method is useful for debugging. Finally, we defined a class called Meta. This class may be used to specify various options related to the data model. Some of the commonly used options are: db_table: This is the name of the table to use for the model. This is useful when the table name generated by Django is a reserved keyword in SQL, or when you want to avoid conflicts if a table with the same name already exists in the database. ordering: This is a list of field names. It declares how objects are ordered when retrieving a list of objects. A column name may be preceded by a minus sign to change the sorting order from ascending to descending. permissions: This lets you declare custom permissions for the data model in addition to add, change, and delete permissions. Permissions should be a list of two-tuples, where each two-tuple should consist of a permission codename and a human-readable name for that permission. For example, you can define a new permission for listing friend bookmarks by using the following Meta class: class Meta: permissions = ( ('can_list_friend_bookmarks', 'Can list friend bookmarks'), ) unique_together: A list of field names that must be unique together. We used the unique_together option here to ensure that a Friendship object is added only once for a particular relationship. There cannot be two Friendship objects with equal to_friend and from_friend fields. This is equivalent to the following SQL declaration: UNIQUE ("from_friend", "to_friend") If you check the SQL generated by Django for this model, you will find something similar to this in the code. After entering the data model code into the bookmarks/models.py file, run the following command to create its corresponding table in the database: $ python manage.py syncdb Now let's experiment with the new model and see how to store and retrieve relations of friendship. Run the interactive console using the following command: $ python manage.py shell Next, retrieve some User objects and build relationships between them (but make sure that you have at least three users in the database): >>> from bookmarks.models import *>>> from django.contrib.auth.models import User>>> user1 = User.objects.get(id=1)>>> user2 = User.objects.get(id=2)>>> user3 = User.objects.get(id=3)>>> friendship1 = Friendship(from_friend=user1, to_friend=user2)>>> friendship1.save()>>> friendship2 = Friendship(from_friend=user1, to_friend=user3)>>> friendship2.save() Now, user2 and user3 are both friends of user1. To retrieve the list of Friendship objects associated with user1, use: >>> user1.friend_set.all()[<Friendship: user1, user2>, <Friendship: user1, user3>] (The actual usernames in output were replaced with user1, user2, and user3 for clarity.) As you may have already noticed, the attribute is named friend_set because we called it so using the related_name option when we created the Friendship model. Next, let's see one way to retrieve the User objects of user1's friends: >>> [friendship.to_friend for friendship in user1.friend_set.all()][<User: user2>, <User: user3>] The last line of code uses a Python feature called "list" comprehension to build the list of User objects. This feature allows us to build a list by iterating through another list. Here, we built the User list by iterating over a list of Friendship objects. If this syntax looks unfamiliar, please refer to the List Comprehension section in the Python tutorial. Notice that user1 has user2 as a friend, but the opposite is not true. >>> user2.friend_set.all() [] In other words, the Friendship model works only in one direction. To add user1 as a friend of user2, we need to construct another Friendship object. >>> friendship3 = Friendship(from_friend=user2, to_friend=user1)>>> friendship3.save()>>> user2.friend_set.all() [<Friendship: user2, user1>] By reversing the arguments passed to the Friendship constructor, we built a relationship in the other way. Now user1 is a friend of user2 and vice-versa. Experiment more with the model to make sure that you understand how it works. Once you feel comfortable with it, move to the next section, where we will write views to utilize the data model. Things will only get more exciting from now on!
Read more
  • 0
  • 0
  • 9485

article-image-squid-proxy-server-3-getting-started
Packt
06 Apr 2011
12 min read
Save for later

Squid Proxy Server 3: getting started

Packt
06 Apr 2011
12 min read
What is a proxy server? A proxy server is a computer system sitting between the client requesting a web document and the target server (another computer system) serving the document. In its simplest form, a proxy server facilitates communication between client and target server without modifying requests or replies. When we initiate a request for a resource from the target server, the proxy server hijacks our connection and represents itself as a client to the target server, requesting the resource on our behalf. If a reply is received, the proxy server returns it to us, giving a feel that we have communicated with the target server. In advanced forms, a proxy server can filter requests based on various rules and may allow communication only when requests can be validated against the available rules. The rules are generally based on an IP address of a client or target server, protocol, content type of web documents, web content type, and so on. As seen in the preceding image, clients can't make direct requests to the web servers. To facilitate communication between clients and web servers, we have connected them using a proxy server which is acting as a medium of communication for clients and web servers. Sometimes, a proxy server can modify requests or replies, or can even store the replies from the target server locally for fulfilling the same request from the same or other clients at a later stage. Storing the replies locally for use at a later time is known as caching. Caching is a popular technique used by proxy servers to save bandwidth, empowering web servers, and improving the end user's browsing experience. Proxy servers are mostly deployed to perform the following: Reduce bandwidth usage Enhance the user's browsing experience by reducing page load time which, in turn, is achieved by caching web documents Enforce network access policies Monitoring user traffic or reporting Internet usage for individual users or groups Enhance user privacy by not exposing a user's machine directly to Internet Distribute load among different web servers to reduce load on a single server Empower a poorly performing web server Filter requests or replies using an integrated virus/malware detection system Load balance network traffic across multiple Internet connections Relay traffic around within a local area network In simple terms, a proxy server is an agent between a client and target server that has a list of rules against which it validates every request or reply, and then allows or denies access accordingly. What is a reverse proxy? Reverse proxying is a technique of storing the replies or resources from a web server locally so that the subsequent requests to the same resource can be satisfied from the local copy on the proxy server, sometimes without even actually contacting the web server. The proxy server or web cache checks if the locally stored copy of the web document is still valid before serving the cached copy. The life of the locally stored web document is calculated from the additional HTTP headers received from the web server. Using HTTP headers, web servers can control whether a given document/response should be cached by a proxy server or not. Web caching is mostly used: To reduce bandwidth usage. A large number of static web documents like CSS and JavaScript files, images, videos, and so on can be cached as they don't change frequently and constitutes the major part of a response from a web server. By ISPs to reduce average page load time to enhance browsing experience for their customers on Dial-Up or broadband. To take a load off a very busy web server by serving static pages/documents from a proxy server's cache. How to download Squid Squid is available in several forms (compressed source archives, source code from a version control system, binary packages such as RPM, DEB, and so on) from Squid's official website, various Squid mirrors worldwide, and software repositories of almost all the popular operating systems. Squid is also shipped with many Linux/Unix distributions. There are various versions and releases of Squid available for download from Squid's official website. To get the most out of a Squid installation its best to check out the latest source code from a Version Control System (VCS) so that we get the latest features and fixes. But be warned, the latest source code from a VCS is generally leading edge and may not be stable or may not even work properly. Though code from a VCS is good for learning or testing Squid's new features, you are strongly advised not to use code from a VCS for production deployments. If we want to play safe, we should probably download the latest stable version or stable version from the older releases. Stable versions are generally tested before they are released and are supposed to work out of the box. Stable versions can directly be used in production deployments. Time for action – identifying the right version A list of available versions of Squid is maintained here. For production environments, we should use versions listed under the Stable Versions section only. If we want to test new Squid features in our environment or if we intend to provide feedback to the Squid community about the new version, then we should be using one of the Beta Versions. As we can see in the preceding screenshot, the website contains the First Production Release Date and Latest Release Date for the stable versions. If we click on any of the versions, we are directed to a page containing a list of all the releases in that particular version. Let's have a look at the page for version 3.1: For every release, along with a release date, there are links for downloading compressed source archives. Different versions of Squid may have different features. For example, all the features available in Squid version 2.7 may or may not be available in newer versions such as Squid 3.x. Some features may have been deprecated or have become redundant over time and they are generally removed. On the other hand, Squid 3.x may have several new features or existing features in an improved and revised manner. Therefore, we should always aim for the latest version, but depending on the environment, we may go for stable or beta version. Also, if we need specific features that are not available in the latest version, we may choose from the available releases in a different branch. What just happened? We had a brief look at the pages containing the different versions and releases of Squid, on Squid's official website. We also learned which versions and releases that we should download and use for different types of usage. Methods of obtaining Squid After identifying the version of Squid that we should be using for compiling and installation, let's have a look at the ways in which we can obtain Squid release 3.1.10. Using source archives Compressed source archives are the most popular way of getting Squid. To download the source archive, please visit Squid download page, http://www.squid-cache.org/Download/. This web page has links for downloading the different versions and releases of Squid, either from the official website or available mirrors worldwide. We can use either HTTP or FTP for getting the Squid source archive. Time for action – downloading Squid Now we are going to download Squid 3.1.10 from Squid's official website: Let's go to the web page. Now we need to click on the link to Version 3.1, as shown in the following screenshot: We'll be taken to a page displaying the various releases in version 3.1. The link with the display text tar.gz in the Download column is a link to the compressed source archive for Squid release 3.1.10, as shown in the following screenshot: To download Squid 3.1.10 using the web browser, just click on the link. Alternatively, we can use wget to download the source archive from the command line as follows: wget http://www.squid-cache.org/Versions/v3/3.1/squid-3.1.10.tar.gz What just happened? We successfully retrieved Squid version 3.1.10 from Squid's official website. The process of retrieving other stable or beta versions is very similar. Obtaining the latest source code from Bazaar VCS Advanced users may be interested in getting the very latest source code from the Squid code repository, using Bazaar. We can safely skip this section if we are not familiar with VCS in general. Bazaar is a popular version control system used to track project history and facilitate collaboration. From version 3.x onwards, Squid source code has been migrated to Bazaar. Therefore, we should ensure that we have Bazaar installed on our system in order to checkout the source code from repository. To find out more about Bazaar or for Bazaar installation and configuration manuals, please visit Bazaar's official website. Once we have setup Bazaar, we should head to the Squid code repository mirrored on Launchpad. From here we can browse all the versions and branches of Squid. Let's get ourselves familiar with the page layout: In the previous screenshot, Series: trunk represents the development branch, which contains code that is still in development and is not ready for production use. The branches with the status Mature are stable and can be used right away in production environments. Time for action – using Bazaar to obtain source code Now that we are familiar with the various branches, versions, and releases. Let's proceed to checking out the source code with Bazaar. To download code from any branch, the syntax for the command is as follows: bzr branch lp:squid[/branch[/version]] branch and version are optional parameters in the previous code. So, if we want to get branch 3.1, then the command will be as follows: bzr branch lp:squid/3.1 The previous command will fetch source code from Launchpad and may take a considerable amount of time, depending on the Internet connection. If we are willing to download source code for Squid version 3.1.10, then the command will be as follows: bzr branch lp:squid/3.1/3.1.10 In the previous code, 3.1 is the branch name and 3.1.10 is the specific version of Squid that we want to checkout. What just happened? We learned to fetch the source code for any Squid branch or release using Bazaar from Squid's source code hosted on Launchpad. Have a go hero – fetching the source code Using the command syntax that we learned in the previous section, fetch the source code for Squid version 3.0.stable25 from Launchpad. Solution: bzr branch lp:squid/3.0/3.0.stable25 Explanation: If we browse to the particular version on Launchpad, the version number used in the command becomes obvious. Using binary packages Squid binary packages are pre-compiled and ready to install software bundles. Binary packages are available in the software repositories of almost all Linux/Unix-based operating systems. Depending on the operating system, only stable and sometimes well tested beta versions make it to the software repositories, so they are ready for production use. Installing Squid Squid can be installed using the source code we obtained in the previous section, using a package manager which, in turn, uses the binary package available for our operating system. Let's have a detailed look at the ways in which we can install Squid. Installing Squid from source code Installing Squid from source code is a three step process: Select the features and operating system-specific settings. Compile the source code to generate the executables. Place the generated executables and other required files in their designated locations for Squid to function properly. We can perform some of the above steps using automated tools that make the compilation and installation process relatively easy. Compiling Squid Compiling Squid is a process of compiling several files containing C/C++ source code and generating executables. Compiling Squid is really easy and can be done in a few steps. For compiling Squid, we need an ANSI C/C++ compliant compiler. If we already have a GNU C/C++ Compiler (GNU Compiler Collection (GCC) and g++, which are available on almost every Linux/Unix-based operating system by default), we are ready to begin the actual compilation. Why compile? Compiling Squid is a bit of a painful task compared to installing Squid from the binary package. However, we recommend compiling Squid from the source instead of using pre-compiled binaries. Let's walk through a few advantages of compiling Squid from the source: While compiling we can enable extra features, which may not be enabled in the pre-compiled binary package. When compiling, we can also disable extra features that are not needed for a particular environment. For example, we may not need Authentication helpers or ICMP support. configure probes the system for several features and enables or disables them accordingly, while pre-compiled binary packages will have the features detected for the system the source was compiled on. Using configure, we can specify an alternate location for installing Squid. We can even install Squid without root or super user privileges, which may not be possible with pre-compiled binary package. Though compiling Squid from source has a lot of advantages over installing from the binary package, the binary package has its own advantages. For example, when we are in damage control mode or a crisis situation and we need to get the proxy server up and running really quickly, using a binary package for installation will provide a quicker installation. Uncompressing the source archive If we obtained the Squid in a compressed archive format, we must extract it before we can proceed any further. If we obtained Squid from Launchpad using Bazaar, we don't need to perform this step. tar -xvzf squid-3.1.10.tar.gz tar is a popular command which is used to extract compressed archives of various types. On the other hand, it can also be used to compress many files into a single archive. The preceding command will extract the archive to a directory named squid-3.1.10.
Read more
  • 0
  • 0
  • 9481

article-image-interfaces
Packt
17 May 2016
19 min read
Save for later

Expert Python Programming: Interfaces

Packt
17 May 2016
19 min read
This article by, Michał Jaworski and Tarek Ziadé, the authors of the book, Expert Python Programming - Second Edition, will mainly focus on interfaces. (For more resources related to this topic, see here.) An interface is a definition of an API. It describes a list of methods and attributes a class should have to implement with the desired behavior. This description does not implement any code but just defines an explicit contract for any class that wishes to implement the interface. Any class can then implement one or several interfaces in whichever way it wants. While Python prefers duck-typing over explicit interface definitions, it may be better to use them sometimes. For instance, explicit interface definition makes it easier for a framework to define functionalities over interfaces. The benefit is that classes are loosely coupled, which is considered as a good practice. For example, to perform a given process, a class A does not depend on a class B, but rather on an interface I. Class B implements I, but it could be any other class. The support for such a technique is built-in in many statically typed languages such as Java or Go. The interfaces allow the functions or methods to limit the range of acceptable parameter objects that implement a given interface, no matter what kind of class it comes from. This allows for more flexibility than restricting arguments to given types or their subclasses. It is like an explicit version of duck-typing behavior: Java uses interfaces to verify a type safety at compile time rather than use duck-typing to tie things together at run time. Python has a completely different typing philosophy to Java, so it does not have native support for interfaces. Anyway, if you would like to have more explicit control on application interfaces, there are generally two solutions to choose from: Use some third-party framework that adds a notion of interfaces Use some of the advanced language features to build your methodology for handling interfaces. Using zope.interface There are a few frameworks that allow you to build explicit interfaces in Python. The most notable one is a part of the Zope project. It is the zope.interface package. Although, nowadays, Zope is not as popular as it used to be, the zope.interface package is still one of the main components of the Twisted framework. The core class of the zope.interface package is the Interface class. It allows you to explicitly define a new interface by subclassing. Let's assume that we want to define the obligatory interface for every implementation of a rectangle: from zope.interface import Interface, Attribute class IRectangle(Interface): width = Attribute("The width of rectangle") height = Attribute("The height of rectangle") def area(): """ Return area of rectangle """ def perimeter(): """ Return perimeter of rectangle """ Some important things to remember when defining interfaces with zope.interface are as follows: The common naming convention for interfaces is to use I as the name suffix. The methods of the interface must not take the self parameter. As the interface does not provide concrete implementation, it should consist only of empty methods. You can use the pass statement, raise NotImplementedError, or provide a docstring (preferred). An interface can also specify the required attributes using the Attribute class. When you have such a contract defined, you can then define new concrete classes that provide implementation for our IRectangle interface. In order to do that, you need to use the implementer() class decorator and implement all of the defined methods and attributes: @implementer(IRectangle) class Square: """ Concrete implementation of square with rectangle interface """ def __init__(self, size): self.size = size @property def width(self): return self.size @property def height(self): return self.size def area(self): return self.size ** 2 def perimeter(self): return 4 * self.size @implementer(IRectangle) class Rectangle: """ Concrete implementation of rectangle """ def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def perimeter(self): return self.width * 2 + self.height * 2 It is common to say that the interface defines a contract that a concrete implementation needs to fulfill. The main benefit of this design pattern is being able to verify consistency between contract and implementation before the object is being used. With the ordinary duck-typing approach, you only find inconsistencies when there is a missing attribute or method at runtime. With zope.interface, you can introspect the actual implementation using two methods from the zope.interface.verify module to find inconsistencies early on: verifyClass(interface, class_object): This verifies the class object for existence of methods and correctness of their signatures without looking for attributes verifyObject(interface, instance): This verifies the methods, their signatures, and also attributes of the actual object instance Since we have defined our interface and two concrete implementations, let's verify their contracts in an interactive session: >>> from zope.interface.verify import verifyClass, verifyObject >>> verifyObject(IRectangle, Square(2)) True >>> verifyClass(IRectangle, Square) True >>> verifyObject(IRectangle, Rectangle(2, 2)) True >>> verifyClass(IRectangle, Rectangle) True Nothing impressive. The Rectangle and Square classes carefully follow the defined contract so there is nothing more to see than a successful verification. But what happens when we make a mistake? Let's see an example of two classes that fail to provide full IRectangle interface implementation: @implementer(IRectangle) class Point: def __init__(self, x, y): self.x = x self.y = y @implementer(IRectangle) class Circle: def __init__(self, radius): self.radius = radius def area(self): return math.pi * self.radius ** 2 def perimeter(self): return 2 * math.pi * self.radius The Point class does not provide any method or attribute of the IRectangle interface, so its verification will show inconsistencies already on the class level: >>> verifyClass(IRectangle, Point) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "zope/interface/verify.py", line 102, in verifyClass return _verify(iface, candidate, tentative, vtype='c') File "zope/interface/verify.py", line 62, in _verify raise BrokenImplementation(iface, name) zope.interface.exceptions.BrokenImplementation: An object has failed to implement interface <InterfaceClass __main__.IRectangle> The perimeter attribute was not provided. The Circle class is a bit more problematic. It has all the interface methods defined but breaks the contract on the instance attribute level. This is the reason why, in most cases, you need to use the verifyObject() function to completely verify the interface implementation: >>> verifyObject(IRectangle, Circle(2)) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "zope/interface/verify.py", line 105, in verifyObject return _verify(iface, candidate, tentative, vtype='o') File "zope/interface/verify.py", line 62, in _verify raise BrokenImplementation(iface, name) zope.interface.exceptions.BrokenImplementation: An object has failed to implement interface <InterfaceClass __main__.IRectangle> The width attribute was not provided. Using zope.inteface is an interesting way to decouple your application. It allows you to enforce proper object interfaces without the need for the overblown complexity of multiple inheritance, and it also allows to catch inconsistencies early. However, the biggest downside of this approach is the requirement that you explicitly define that the given class follows some interface in order to be verified. This is especially troublesome if you need to verify instances coming from external classes of built-in libraries. zope.interface provides some solutions for that problem, and you can of course handle such issues on your own by using the adapter pattern, or even monkey-patching. Anyway, the simplicity of such solutions is at least arguable. Using function annotations and abstract base classes Design patterns are meant to make problem solving easier and not to provide you with more layers of complexity. The zope.interface is a great concept and may greatly fit some projects, but it is not a silver bullet. By using it, you may soon find yourself spending more time on fixing issues with incompatible interfaces for third-party classes and providing never-ending layers of adapters instead of writing the actual implementation. If you feel that way, then this is a sign that something went wrong. Fortunately, Python supports for building lightweight alternative to the interfaces. It's not a full-fledged solution like zope.interface or its alternatives but it generally provides more flexible applications. You may need to write a bit more code, but in the end you will have something that is more extensible, better handles external types, and may be more future proof. Note that Python in its core does not have explicit notions of interfaces, and probably will never have, but has some of the features that allow you to build something that resembles the functionality of interfaces. The features are: Abstract base classes (ABCs) Function annotations Type annotations The core of our solution is abstract base classes, so we will feature them first. As you probably know, the direct type comparison is considered harmful and not pythonic. You should always avoid comparisons as follows: assert type(instance) == list Comparing types in functions or methods that way completely breaks the ability to pass a class subtype as an argument to the function. The slightly better approach is to use the isinstance() function that will take the inheritance into account: assert isinstance(instance, list) The additional advantage of isinstance() is that you can use a larger range of types to check the type compatibility. For instance, if your function expects to receive some sort of sequence as the argument, you can compare against the list of basic types: assert isinstance(instance, (list, tuple, range)) Such a way of type compatibility checking is OK in some situations but it is still not perfect. It will work with any subclass of list, tuple, or range, but will fail if the user passes something that behaves exactly the same as one of these sequence types but does not inherit from any of them. For instance, let's relax our requirements and say that you want to accept any kind of iterable as an argument. What would you do? The list of basic types that are iterable is actually pretty long. You need to cover list, tuple, range, str, bytes, dict, set, generators, and a lot more. The list of applicable built-in types is long, and even if you cover all of them it will still not allow you to check against the custom class that defines the __iter__() method, but will instead inherit directly from object. And this is the kind of situation where abstract base classes (ABC) are the proper solution. ABC is a class that does not need to provide a concrete implementation but instead defines a blueprint of a class that may be used to check against type compatibility. This concept is very similar to the concept of abstract classes and virtual methods known in the C++ language. Abstract base classes are used for two purposes: Checking for implementation completeness Checking for implicit interface compatibility So, let's assume we want to define an interface which ensures that a class has a push() method. We need to create a new abstract base class using a special ABCMeta metaclass and an abstractmethod() decorator from the standard abc module: from abc import ABCMeta, abstractmethod class Pushable(metaclass=ABCMeta): @abstractmethod def push(self, x): """ Push argument no matter what it means """ The abc module also provides an ABC base class that can be used instead of the metaclass syntax: from abc import ABCMeta, abstractmethod class Pushable(metaclass=ABCMeta): @abstractmethod def push(self, x): """ Push argument no matter what it means """ Once it is done, we can use that Pushable class as a base class for concrete implementation and it will guard us from the instantiation of objects that would have incomplete implementation. Let's define DummyPushable, which implements all interface methods and the IncompletePushable that breaks the expected contract: class DummyPushable(Pushable): def push(self, x): return class IncompletePushable(Pushable): pass If you want to obtain the DummyPushable instance, there is no problem because it implements the only required push() method: >>> DummyPushable() <__main__.DummyPushable object at 0x10142bef0> But if you try to instantiate IncompletePushable, you will get TypeError because of missing implementation of the interface() method: >>> IncompletePushable() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class IncompletePushable with abstract methods push The preceding approach is a great way to ensure implementation completeness of base classes but is as explicit as the zope.interface alternative. The DummyPushable instances are of course also instances of Pushable because Dummy is a subclass of Pushable. But how about other classes with the same methods but not descendants of Pushable? Let's create one and see: >>> class SomethingWithPush: ... def push(self, x): ... pass ... >>> isinstance(SomethingWithPush(), Pushable) False Something is still missing. The SomethingWithPush class definitely has a compatible interface but is not considered as an instance of Pushable yet. So, what is missing? The answer is the __subclasshook__(subclass) method that allows you to inject your own logic into the procedure that determines whether the object is an instance of a given class. Unfortunately, you need to provide it by yourself, as abc creators did not want to constrain the developers in overriding the whole isinstance() mechanism. We got full power over it, but we are forced to write some boilerplate code. Although you can do whatever you want to, usually the only reasonable thing to do in the __subclasshook__() method is to follow the common pattern. The standard procedure is to check whether the set of defined methods are available somewhere in the MRO of the given class: from abc import ABCMeta, abstractmethod class Pushable(metaclass=ABCMeta): @abstractmethod def push(self, x): """ Push argument no matter what it means """ @classmethod def __subclasshook__(cls, C): if cls is Pushable: if any("push" in B.__dict__ for B in C.__mro__): return True return NotImplemented With the __subclasshook__() method defined that way, you can now confirm that the instances that implement the interface implicitly are also considered instances of the interface: >>> class SomethingWithPush: ... def push(self, x): ... pass ... >>> isinstance(SomethingWithPush(), Pushable) True Unfortunately, this approach to the verification of type compatibility and implementation completeness does not take into account the signatures of class methods. So, if the number of expected arguments is different in implementation, it will still be considered compatible. In most cases, this is not an issue, but if you need such fine-grained control over interfaces, the zope.interface package allows for that. As already said, the __subclasshook__() method does not constrain you in adding more complexity to the isinstance() function's logic to achieve a similar level of control. The two other features that complement abstract base classes are function annotations and type hints. Function annotation is the syntax element. It allows you to annotate functions and their arguments with arbitrary expressions. This is only a feature stub that does not provide any syntactic meaning. There is no utility in the standard library that uses this feature to enforce any behavior. Anyway, you can use it as a convenient and lightweight way to inform the developer of the expected argument interface. For instance, consider this IRectangle interface rewritten from zope.interface to abstract the base class: from abc import ( ABCMeta, abstractmethod, abstractproperty ) class IRectangle(metaclass=ABCMeta): @abstractproperty def width(self): return @abstractproperty def height(self): return @abstractmethod def area(self): """ Return rectangle area """ @abstractmethod def perimeter(self): """ Return rectangle perimeter """ @classmethod def __subclasshook__(cls, C): if cls is IRectangle: if all([ any("area" in B.__dict__ for B in C.__mro__), any("perimeter" in B.__dict__ for B in C.__mro__), any("width" in B.__dict__ for B in C.__mro__), any("height" in B.__dict__ for B in C.__mro__), ]): return True return NotImplemented If you have a function that works only on rectangles, let's say draw_rectangle(), you could annotate the interface of the expected argument as follows: def draw_rectangle(rectangle: IRectange): ... This adds nothing more than information for the developer about expected information. And even this is done through an informal contract because, as we know, bare annotations contain no syntactic meaning. However, they are accessible at runtime, so we can do something more. Here is an example implementation of a generic decorator that is able to verify interface from function annotation if it is provided using abstract base classes: def ensure_interface(function): signature = inspect.signature(function) parameters = signature.parameters @wraps(function) def wrapped(*args, **kwargs): bound = signature.bind(*args, **kwargs) for name, value in bound.arguments.items(): annotation = parameters[name].annotation if not isinstance(annotation, ABCMeta): continue if not isinstance(value, annotation): raise TypeError( "{} does not implement {} interface" "".format(value, annotation) ) function(*args, **kwargs) return wrapped Once it is done, we can create some concrete class that implicitly implements the IRectangle interface (without inheriting from IRectangle) and update the implementation of the draw_rectangle() function to see how the whole solution works: class ImplicitRectangle: def __init__(self, width, height): self._width = width self._height = height @property def width(self): return self._width @property def height(self): return self._height def area(self): return self.width * self.height def perimeter(self): return self.width * 2 + self.height * 2 @ensure_interface def draw_rectangle(rectangle: IRectangle): print( "{} x {} rectangle drawing" "".format(rectangle.width, rectangle.height) ) If we feed the draw_rectangle() function with an incompatible object, it will now raise TypeError with a meaningful explanation: >>> draw_rectangle('foo') Traceback (most recent call last): File "<input>", line 1, in <module> File "<input>", line 101, in wrapped TypeError: foo does not implement <class 'IRectangle'> interface But if we use ImplicitRectangle or anything else that resembles the IRectangle interface, the function executes as it should: >>> draw_rectangle(ImplicitRectangle(2, 10)) 2 x 10 rectangle drawing Our example implementation of ensure_interface() is based on the typechecked() decorator from the typeannotations project that tries to provide run-time checking capabilities (refer to https://github.com/ceronman/typeannotations). Its source code might give you some interesting ideas about how to process type annotations to ensure run-time interface checking. The last feature that can be used to complement this interface pattern landscape are type hints. Type hints are described in detail by PEP 484 and were added to the language quite recently. They are exposed in the new typing module and are available from Python 3.5. Type hints are built on top of function annotations and reuse this slightly forgotten syntax feature of Python 3. They are intended to guide type hinting and check for various yet-to-come Python type checkers. The typing module and PEP 484 document aim to provide a standard hierarchy of types and classes that should be used for describing type annotations. Still, type hints do not seem to be something revolutionary because this feature does not come with any type checker built-in into the standard library. If you want to use type checking or enforce strict interface compatibility in your code, you need to create your own tool because there is none worth recommendation yet. This is why we won't dig into details of PEP 484. Anyway, type hints and the documents describing them are worth mentioning because if some extraordinary solution emerges in the field of type checking in Python, it is highly probable that it will be based on PEP 484. Using collections.abc Abstract base classes are like small building blocks for creating a higher level of abstraction. They allow you to implement really usable interfaces but are very generic and designed to handle lot more than this single design pattern. You can unleash your creativity and do magical things but building something generic and really usable may require a lot of work. Work that may never pay off. This is why custom abstract base classes are not used so often. Despite that, the collections.abc module provides a lot of predefined ABCs that allow to verify interface compatibility of many basic Python types. With base classes provided in this module, you can check, for example, whether a given object is callable, mapping, or if it supports iteration. Using them with the isinstance() function is way better than comparing them against the base python types. You should definitely know how to use these base classes even if you don't want to define your own custom interfaces with ABCMeta. The most common abstract base classes from collections.abc that you will use from time to time are: Container: This interface means that the object supports the in operator and implements the __contains__() method Iterable: This interface means that the object supports the iteration and implements the __iter__() method Callable: This interface means that it can be called like a function and implements the __call__() method Hashable: This interface means that the object is hashable (can be included in sets and as key in dictionaries) and implements the __hash__ method Sized: This interface means that the object has size (can be a subject of the len() function) and implements the __len__() method A full list of the available abstract base classes from the collections.abc module is available in the official Python documentation (refer to https://docs.python.org/3/library/collections.abc.html). Summary Design patterns are reusable, somewhat language-specific solutions to common problems in software design. They are a part of the culture of all developers, no matter what language they use. We learned a small part of design patterns in this article. We covered what interfaces are and how they can be used in Python. Resources for Article: Further resources on this subject: Creating User Interfaces [article] Graphical User Interfaces for OpenSIPS 1.6 [article]
Read more
  • 0
  • 0
  • 9477

article-image-introduction-watchkit
Packt
04 Sep 2015
7 min read
Save for later

Introduction to WatchKit

Packt
04 Sep 2015
7 min read
In this article by Hossam Ghareeb, author of the book Application Development with Swift, we will talk about a new technology, WatchKit, and a new era of wearable technologies. Now technology is a part of all aspects of our lives, even wearable objects. You can see smart watches such as the new Apple watch or glasses such as Google glass. We will go through the new WatchKit framework to learn how to extend your iPhone app functionalities to your wrist. (For more resources related to this topic, see here.) Apple watch Apple watch is a new device on your wrist that can be used to extend your iPhone app functionality; you can access the most important information and respond in easy ways using the watch. The watch is now available in most countries in different styles and models so that everyone can find a watch that suits them. When you get your Apple watch, you can pair it with your iPhone. The watch can't be paired with the iPad; it can only be paired with your iPhone. To run third-party apps on your watch, iPhone should be paired with the watch. Once paired, when you install any app on your iPhone that has an extension for the watch, the app will be installed on the watch automatically and wirelessly. WatchKit WatchKit is a new framework to build apps for Apple watch. To run third-party apps on Apple watch, you need the watch to be connected to the iPhone. WatchKit helps you create apps for Apple watch by creating two targets in Xcode: The WatchKit app: The WatchKit app is an executable app to be installed on your watch, and you can install or uninstall it from your iPhone. The WatchKit app contains the storyboard file and resources files. It doesn't contain any source code, just the interface and resource files. The WatchKit extension: This extension runs on the iPhone and has the InterfaceControllers file for your storyboard. This extension just contains the model and controller classes. The actions and outlets from the previous WatchKit app will be linked to these controller files in the WatchKit extension. These bundles—the WatchKit extension and WatchKit app—are put together and packed inside the iPhone application. When the user installs the iPhone app, the system will prompt the user to install the WatchKit app if there is a paired watch. Using WatchKit, you can extend your iOS app in three different ways: The WatchKit app As we mentioned earlier, the WatchKit app is an app installed on Apple watch and the user can find it in the list of Watch apps. The user can launch, control, and interact with the app. Once the app is launched, the WatchKit extension on the iPhone app will run in the background to update a user interface, perform any logic required, and respond to user actions. Note that the iPhone app can't launch or wake up the WatchKit extension or the WatchKit app. However, the WatchKit extension can ask the system to launch the iPhone app and this will be performed in the background. Glances Glances are single interfaces that the user can navigate between. The glance view is just read-only information, which means that you can't add any interactive UI controls such as buttons and switches. Apps should use glances to display very important and timely information. The glance view is a nonscrolling view, so your glance view should fit the watch screen. Avoid using tables and maps in interface controllers and focus on delivering the most important information in a nice way. Once the user clicks on the glance view, the watch app will be launched. The glance view is optional in your app. The glance interface and its interface controller files are a part of your WatchKit extension and WatchKit app. The glance interface resides in a storyboard, which resides in the WatchKit app. The interface controller that is responsible for filling the view with the timely important information is located in the WatchKit extension, which runs in the background in the iPhone app, as we said before. Actionable notifications For sure, you can handle and respond to local and remote notifications in an easy and fast way using Apple watch. WatchKit helps you build user interfaces for the notification that you want to handle in your WatchKit app. WatchKit helps you add actionable buttons so that the user can take action based on the notification. For example, if a notification for an invitation is sent to you, you can take action to accept or reject the notification from your wrist. You can respond to these actions easily in interface controllers in WatchKit extension. Working with WatchKit Enough talking about theory, lets see some action. Go to our lovely Xcode and create a new single-view application and name it WatchKitDemo. Don't forget to select Swift as the app language. Then navigate to File | New | Target to create a new target for the WatchKit app: After you select the target, in the pop-up window, from the left side under iOS choose Apple Watch and select WatchKit App. Check the following screenshot: After you click on Next, it will ask you which application to embed the target in and which scenes to include. Please check the Include Notification Scene and Include Glance Scene options, as shown in the following screenshot: Click on Finish, and now you have an iPhone app with the built-in WatchKit extension and WatchKit app. Xcode targets Now your project should be divided into three parts. Check the following screenshot and let's explain these parts: As you see in this screenshot, the project files are divided into three sections. In section 1, you can see the iPhone app source files, interface files or storyboard, and resources files. In section 2, you can find the WatchKit extension, which contains only interface controllers and model files. Again, as we said before, this extension also runs in iPhone in the background. In section 3, you can see the WatchKit app, which runs in Apple watch itself. As we see, it contains the storyboard and resources files. No source code can be added in this target. Interface controllers In the WatchKit extension of your Xcode project, open InterfaceController.swift. You will find the interface controller file for the scene that exists in Interface.storyboard in the WatchKit app. The InterfaceController file extends from WKInterfaceController, which is the base class for interface controllers. Forget the UI classes that you were using in the iOS apps from the UIKit framework, as it has different interface controller classes in WatchKit and they are very limited in configuration and customization. In the InterfaceController file, you can find three important methods that explain the lifecycle of your controller: awakeWithContext, willActivate, and didDeactivate. Another important method that can be overridden for the lifecycle is called init, but it's not implemented in the controller file. Let's now explain the four lifecycle methods: init: You can consider this as your first chance to update your interface elements. awakeWithContext: This is called after the init method and contains context data that can be used to update your interface elements or to perform some logical operations on these data. Context data is passed between interface controllers when you push or present another controller and you want to pass some data. willActivate: Here, your scene is about to be visible onscreen, and its your last chance to update your UI. Try to put simple UI changes here in this method so as not to cause freezing in UI. didDeactivate: Your scene is about to be invisible and, if you want to clean up your code, it's time to stop animations or timers. Summary In this article, we covered a very important topic: how to develop apps for the new wearable technology, Apple watch. We first gave a quick introduction about the new device and how it can communicate with paired iPhones. We then talked about WatchKit, the new framework, that enables you to develop apps for Apple watch and design its interface. Apple has designed the watch to contain only the storyboard and resources files. All logic and operations are performed in the iPhone app in the background. Resources for Article: Further resources on this subject: Flappy Swift [article] Playing with Swift [article] Using OpenStack Swift [article]
Read more
  • 0
  • 0
  • 9475

article-image-new-programming-video-courses-for-march-2019
Richard Gall
04 Mar 2019
6 min read
Save for later

New programming video courses for March 2019

Richard Gall
04 Mar 2019
6 min read
It’s not always easy to know what to learn next if you’re a programmer. Industry shifts can be subtle but they can sometimes be dramatic, making it incredibly important to stay on top of what’s happening both in your field and beyond. No one person can make that decision for you. All the thought leadership and mentorship in the world isn’t going to be able to tell you what’s right for you when it comes to your career. But this list of videos, released last month, might give you a helping hand as to where to go next when it comes to your learning… New data science and artificial intelligence video courses for March Apache Spark is carving out a big presence as the go-to software for big data. Two videos from February focus on Spark - Distributed Deep Learning with Apache Spark and Apache Spark in 7 Days. If you’re new to Spark and want a crash course on the tool, then clearly, our video aims to get you up and running quickly. However, Distributed Deep Learning with Apache Spark offers a deeper exploration that shows you how to develop end to end deep learning pipelines that can leverage the full potential of cutting edge deep learning techniques. While we’re on the subject of machine learning, other choice video courses for March include TensorFlow 2.0 New Features (we’ve been eagerly awaiting it and it finally looks like we can see what it will be like), Hands On Machine Learning with JavaScript (yes, you can now do machine learning in the browser), and a handful of interesting videos on artificial intelligence and finance: AI for Finance Machine Learning for Algorithmic Trading Bots with Python Hands on Python for Finance Elsewhere, a number of data visualization video courses prove that communicating and presenting data remains an urgent challenge for those in the data space. Tableau remains one of the definitive tools - you can learn the latest version with Tableau 2019.1 for Data Scientists and Data Visualization Recipes with Python and Matplotlib 3.   New app and web development video courses for March 2019 There are a wealth of video courses for web and app developers to choose from this month. True, Hands-on Machine Learning for JavaScript is well worth a look, but moving past the machine learning hype, there are a number of video courses that take a practical look at popular tools and new approaches to app and web development. Angular’s death has been greatly exaggerated - it remains a pillar of the JavaScript world. While the project’s versioning has arguably been lacking some clarity, if you want to get up to speed with where the framework is today, try Angular 7: A Practical Guide. It’s a video that does exactly what it says on the proverbial tin - it shows off Angular 7 and demonstrates how to start using it in web projects. We’ve also been seeing some uptake of Angular by ASP.NET developers, as it offers a nice complement to the Microsoft framework on the front end side. Our latest video on the combination, Hands-on Web Development with ASP.NET Core and Angular, is another practical look at an effective and increasingly popular approach to full-stack development. Other picks for March include Building Mobile Apps with Ionic 4, a video that brings you right up to date with the recent update that launched in January (interestingly, the project is now backed by web components, not Angular), and a couple of Redux videos - Mastering Redux and Redux Recipes. Redux is still relatively new. Essentially, it’s a JavaScript library that helps you manage application state - because it can be used with a range of different frameworks and libraries, including both Angular and React, it’s likely to go from strength to strength in 2019. Infrastructure, admin and security video courses for March 2019 Node.js is becoming an important library for infrastructure and DevOps engineers. As we move to a cloud native world, it’s a great tool for developing lightweight and modular services. That’s why we’re picking Learn Serverless App Development with Node.js and Azure Functions as one of our top videos for this month. Azure has been growing at a rapid rate over the last 12 months, and while it’s still some way behind AWS, Microsoft’s focus on developer experience is making Azure an increasingly popular platform with developers. For Node developers, this video is a great place to begin - it’s also useful for anyone who simply wants to find out what serverless development actually feels like. Read next: Serverless computing wars: AWS Lambda vs. Azure Functions A partner to this, for anyone beginning Node, is the new Node.js Design Patterns video. In particular, if Node.js is an important tool in your architecture, following design patterns is a robust method of ensuring reliability and resilience. Elsewhere, we have Modern DevOps in Practice, cutting through the consultancy-speak to give you useful and applicable guidance on how to use DevOps thinking in your workflows and processes, and DevOps with Azure, another video that again demonstrates just how impressive Azure is. For those not Azure-inclined, there’s AWS Certified Developer Associate - A Practical Guide, a video that takes you through everything you need to know to pass the AWS Developer Associate exam. There’s also a completely cloud-agnostic video course in the form of Creating a Continuous Deployment Pipeline for Cloud Platforms that’s essential for infrastructure and operations engineers getting to grips with cloud native development.     Learn a new programming language with these new video courses for March Finally, there are a number of new video courses that can help you get to grips with a new programming language. So, perfect if you’ve been putting off your new year’s resolution to learn a new language… Java 11 in 7 Days is a new video that brings you bang up to date with everything in the latest version of Java, while Hands-on Functional Programming with Java will help you rethink and reevaluate the way you use Java. Together, the two videos are a great way for Java developers to kick start their learning and update their skill set.  
Read more
  • 0
  • 0
  • 9473

article-image-introduction-odoo
Packt
04 Sep 2015
12 min read
Save for later

Introduction to Odoo

Packt
04 Sep 2015
12 min read
 In this article by Greg Moss, author of Working with Odoo, he explains that Odoo is a very feature-filled business application framework with literally hundreds of applications and modules available. We have done our best to cover the most essential features of the Odoo applications that you are most likely to use in your business. Setting up an Odoo system is no easy task. Many companies get into trouble believing that they can just install the software and throw in some data. Inevitably, the scope of the project grows and what was supposed to be a simple system ends up being a confusing mess. Fortunately, Odoo's modular design will allow you to take a systematic approach to implementing Odoo for your business. (For more resources related to this topic, see here.) What is an ERP system? An Enterprise Resource Planning (ERP) system is essentially a suite of business applications that are integrated together to assist a company in collecting, managing, and reporting information throughout core business processes. These business applications, typically called modules, can often be independently installed and configured based on the specific needs of the business. As the needs of the business change and grow, additional modules can be incorporated into an existing ERP system to better handle the new business requirements. This modular design of most ERP systems gives companies great flexibility in how they implement the system. In the past, ERP systems were primarily utilized in manufacturing operations. Over the years, the scope of ERP systems have grown to encompass a wide range of business-related functions. Recently, ERP systems have started to include more sophisticated communication and social networking features. Common ERP modules The core applications of an ERP system typically include: Sales Orders Purchase Orders Accounting and Finance Manufacturing Resource Planning (MRP) Customer Relationship Management (CRM) Human Resources (HR) Let's take a brief look at each of these modules and how they address specific business needs. Selling products to your customer Sales Orders, commonly abbreviated as SO, are documents that a business generates when they sell products and services to a customer. In an ERP system, the Sales Order module will usually allow management of customers and products to optimize efficiency for data entry of the sales order. Many sales orders begin as customer quotes. Quotes allow a salesperson to collect order information that may change as the customer makes decisions on what they want in their final order. Once a customer has decided exactly what they wish to purchase, the quote is turned into a sales order and is confirmed for processing. Depending on the requirements of the business, there are a variety of methods to determine when a customer is invoiced or billed for the order. This preceding screenshot shows a sample sales order in Odoo. Purchasing products from suppliers Purchase Orders, often known as PO, are documents that a business generates when they purchase products from a vendor. The Purchase Order module in an ERP system will typically include management of vendors (also called suppliers) as well as management of the products that the vendor carries. Much like sales order quotes, a purchase order system will allow a purchasing department to create draft purchase orders before they are finalized into a specific purchasing request. Often, a business will configure the Sales Order and Purchase Order modules to work together to streamline business operations. When a valid sales order is entered, most ERP systems will allow you to configure the system so that a purchase order can be automatically generated if the required products are not in stock to fulfill the sales order. ERP systems will allow you to set minimum quantities on-hand or order limits that will automatically generate purchase orders when inventory falls below a predetermined level. When properly configured, a purchase order system can save a significant amount of time in purchasing operations and assist in preventing supply shortages. Managing your accounts and financing in Odoo Accounting and finance modules integrate with an ERP system to organize and report business transactions. In many ERP systems, the accounting and finance module is known as GL for General Ledger. All accounting and finance modules are built around a structure known as the chart of accounts. The chart of accounts organizes groups of transactions into categories such as assets, liabilities, income, and expenses. ERP systems provide a lot of flexibility in defining the structure of your chart of accounts to meet the specific requirements for your business. Accounting transactions are grouped by date into periods (typically by month) for reporting purposes. These reports are most often known as financial statements. Common financial statements include balance sheets, income statements, cash flow statements, and statements of owner's equity. Handling your manufacturing operations The Manufacturing Resource Planning (MRP) module manages all the various business operations that go into the manufacturing of products. The fundamental transaction of an MRP module is a manufacturing order, which is also known as a production order in some ERP systems. A manufacturing order describes the raw products or subcomponents, steps, and routings required to produce a finished product. The raw products or subcomponents required to produce the finished product are typically broken down into a detailed list called a bill of materials or BOM. A BOM describes the exact quantities required of each component and are often used to define the raw material costs that go into manufacturing the final products for a company. Often an MRP module will incorporate several submodules that are necessary to define all the required operations. Warehouse management is used to define locations and sublocations to store materials and products as they move through the various manufacturing operations. For example, you may receive raw materials in one warehouse location, assemble those raw materials into subcomponents and store them in another location, then ultimately manufacture the end products and store them in a final location before delivering them to the customer. Managing customer relations in Odoo In today's business environment, quality customer service is essential to being competitive in most markets. A Customer Relationship Management (CRM) module assists a business in better handling the interactions they may have with each customer. Most CRM systems also incorporate a presales component that will manage opportunities, leads, and various marketing campaigns. Typically, a CRM system is utilized the most by the sales and marketing departments within a company. For this reason, CRM systems are often considered to be sales force automation tools or SFA tools. Sales personnel can set up appointments, schedule call backs, and employ tools to manage their communication. More modern CRM systems have started to incorporate social networking features to assist sales personnel in utilizing these newly emerging technologies. Configuring human resource applications in Odoo Human Resource modules, commonly known as HR, manage the workforce- or employee-related information in a business. Some of the processes ordinarily covered by HR systems are payroll, time and attendance, benefits administration, recruitment, and knowledge management. Increased regulations and complexities in payroll and benefits have led to HR modules becoming a major component of most ERP systems. Modern HR modules typically include employee kiosk functions to allow employees to self-administer many tasks such as putting in a leave request or checking on their available vacation time. Finding additional modules for your business requirements In addition to core ERP modules, Odoo has many more official and community-developed modules available. At the time of this article's publication, the Odoo application repository had 1,348 modules listed for version 7! Many of these modules provide small enhancements to improve usability like adding payment type to a sales order. Other modules offer e-commerce integration or complete application solutions, such as managing a school or hospital. Here is a short list of the more common modules you may wish to include in an Odoo installation: Point of Sale Project Management Analytic Accounting Document Management System Outlook Plug-in Country-Specific Accounting Templates OpenOffice Report Designer You will be introduced to various Odoo modules that extend the functionality of the base Odoo system. You can find a complete list of Odoo modules at http://apps.Odoo.com/. This preceding screenshot shows the module selection page in Odoo. Getting quickly into Odoo Do you want to jump in right now and get a look at Odoo 7 without any complex installations? Well, you are lucky! You can access an online installation of Odoo, where you can get a peek at many of the core modules right from your web browser. The installation is shared publicly, so you will not want to use this for any sensitive information. It is ideal, however, to get a quick overview of the software and to get an idea for how the interface functions. You can access a trial version of Odoo at https://www.Odoo.com/start. Odoo – an open source ERP solution Odoo is a collection of business applications that are available under an open source license. For this reason, Odoo can be used without paying license fees and can be customized to suit the specific needs of a business. There are many advantages to open source software solutions. We will discuss some of these advantages shortly. Free your company from expensive software license fees One of the primary downsides of most ERP systems is they often involve expensive license fees. Increasingly, companies must pay these license fees on an annual basis just to receive bug fixes and product updates. Because ERP systems can require companies to devote great amounts of time and money for setup, data conversion, integration, and training, it can be very expensive, often prohibitively so, to change ERP systems. For this reason, many companies feel trapped as their current ERP vendors increase license fees. Choosing open source software solutions, frees a company from the real possibility that a vendor will increase license fees in the years ahead. Modify the software to meet your business needs With proprietary ERP solutions, you are often forced to accept the software solution the vendor provides chiefly "as is". While you may have customization options and can sometimes pay the company to make specific changes, you rarely have the freedom to make changes directly to the source code yourself. The advantages to having the source code available to enterprise companies can be very significant. In a highly competitive market, being able to develop solutions that improve business processes and give your company the flexibility to meet future demands can make all the difference. Collaborative development Open source software does not rely on a group of developers who work secretly to write proprietary code. Instead, developers from all around the world work together transparently to develop modules, prepare bug fixes, and increase software usability. In the case of Odoo, the entire source code is available on Launchpad.net. Here, developers submit their code changes through a structure called branches. Changes can be peer reviewed, and once the changes are approved, they are incorporated into the final source code product. Odoo – AGPL open source license The term open source covers a wide range of open source licenses that have their own specific rights and limitations. Odoo and all of its modules are released under the Affero General Public License (AGPL) version 3. One key feature of this license is that any custom-developed module running under Odoo must be released with the source code. This stipulation protects the Odoo community as a whole from developers who may have a desire to hide their code from everyone else. This may have changed or has been appended recently with an alternative license. You can find the full AGPL license at http://www.gnu.org/licenses/agpl-3.0.html. A real-world case study using Odoo The goal is to do more than just walk through the various screens and reports of Odoo. Instead, we want to give you a solid understanding of how you would implement Odoo to solve real-world business problems. For this reason, this article will present a real-life case study in which Odoo was actually utilized to improve specific business processes. Silkworm, Inc. – a mid-sized screen printing company Silkworm, Inc. is a highly respected mid-sized silkscreen printer in the Midwest that manufactures and sells a variety of custom apparel products. They have been kind enough to allow us to include some basic aspects of their business processes as a set of real-world examples implementing Odoo into a manufacturing operation. Using Odoo, we will set up the company records (or system) from scratch and begin by walking through their most basic sales order process, selling T-shirts. From there, we will move on to manufacturing operations, where custom art designs are developed and then screen printed onto raw materials for shipment to customers. We will come back to this real-world example so that you can see how Odoo can be used to solve real-world business solutions. Although Silkworm is actively implementing Odoo, Silkworm, Inc. does not directly endorse or recommend Odoo for any specific business solution. Every company must do their own research to determine whether Odoo is a good fit for their operation. Summary In this article, we have learned about the ERP system and common ERP modules. An introduction about Odoo and features of it. Resources for Article: Further resources on this subject: Getting Started with Odoo Development[article] Machine Learning in IPython with scikit-learn [article] Making Goods with Manufacturing Resource Planning [article]
Read more
  • 0
  • 0
  • 9467
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-revolutionizing-business-productivity-using-cassidyai
Julian Melanson
28 Jun 2023
6 min read
Save for later

Revolutionizing Business Productivity using CassidyAI

Julian Melanson
28 Jun 2023
6 min read
In recent times, the entrepreneurial environment has seen a surge in innovation, particularly in the realm of artificial intelligence. Among the stalwarts of this revolution is Neo, a startup accelerator masterminded by Silicon Valley investor Ali Partovi. In a groundbreaking move in March, Neo entered a strategic partnership with renowned AI research organization OpenAI, and tech giant Microsoft Corp. The objective was clear: to offer no-cost software and expert advice to startups orienting their focus towards AI. This partnership's results are already tangible, with CassidyAI, a startup championed by content creator Justin Fineberg, being one of the companies benefiting from this initiative.CassidyAI: A Pioneer in AI-Driven Business AutomationFineberg recently announced that CassidyAI is stepping out from the shadows, shedding its stealth mode. CassidyAI's primary function is an embodiment of innovation: facilitating businesses to create customized AI assistants, thus automating tasks, optimizing productivity, and integrating AI across entire organizations. With this aim, CassidyAI is at the forefront of a paradigm shift in business process automation and management.Amplifying Productivity: CassidyAI's VisionAt its core, CassidyAI embraces an ambitious vision: to multiply the productivity of every team within an organization by a factor of ten. This tenfold increase isn't just a lofty goal; it is a transformative approach that involves deploying AI technology across business operations. CassidyAI accomplishes this by providing a platform for generating bespoke AI assistants that cater to individual departmental needs. This process involves training these virtual assistants using the specific knowledge base and data sets of each department.Harnessing AI Across Departments: Versatile Use-CasesThe potential applications of CassidyAI's platform are practically limitless. The diversity of use cases underscores the flexibility and versatility of the AI-assistant creation process. In marketing, for instance, teams can train CassidyAI on their unique writing style and marketing objectives, thereby crafting content that aligns perfectly with the brand image. Similarly, sales teams can enhance their outreach initiatives by leveraging CassidyAI's understanding of the sales pitch, process, and customer profiles.In customer service, AI assistants can respond to inquiries accurately and efficiently, with CassidyAI's ability to access comprehensive support knowledge. Engineering teams can train CassidyAI on their technical stack and engineering methods and architecture, enabling more informed technical decisions and codebase clarity. Product teams can use CassidyAI's profound understanding of their team dynamics and user experience principles to drive product ideation and roadmap collaboration. Finally, HR departments can provide employees with quick access to HR documentation through AI assistants trained to handle such inquiries.Data Security and Transparency: CassidyAI's AssuranceBeyond its vast application range, CassidyAI distinguishes itself through its commitment to data security and transparency. The platform's ability to import knowledge from various platforms ensures a deep understanding of a company's brand, operations, and unique selling propositions. Equally important, all interactions with CassidyAI remain reliable and secure due to their stringent data handling practices and clear citation of sources.Setting Up AI Automation: A No-Code ApproachCassidyAI's approach to implementing AI in businesses is straightforward and code-free, catering to those without programming skills. Businesses begin by securely uploading their internal data and knowledge to train CassidyAI on their unique products, strategies, processes, and more. They then construct AI assistants that are fine-tuned for their distinct use cases, without the need to write a single line of code. Once the AI assistants are ready, they can be shared across the team, fostering an atmosphere of AI adoption and collaboration throughout the organization.Interestingly, the onboarding process for each company joining CassidyAI is currently personally overseen by Fineberg. Although this may limit the pace of early access, it provides a personalized and detailed introduction to CassidyAI’s capabilities and potential. Companies interested in exploring CassidyAI's offerings can request a demo through their website.CassidyAI represents a revolutionary approach to adopting AI technology in businesses. By creating tailored AI assistants that cater to the specific needs of different departments, it offers an opportunity to substantially improve productivity and streamline operations. Its emergence from stealth mode signals a new era of AI-led business automation and provides an exciting glimpse into the future of work. It is anticipated that as CassidyAI gains traction, more businesses will leverage this innovative tool to their advantage, fundamentally transforming their approach to task automation and productivity enhancement.You can browse the website and request a demo here: https://www.cassidyai.comReal-World Use casesHere are some specific examples of how CassidyAI is being used by real businesses:Centrifuge: Centrifuge is using CassidyAI to originate real-world assets and to securitize them. This is helping Centrifuge to provide businesses with access to financing and to reduce risk.Tinlake: Tinlake is using CassidyAI to automate the process of issuing and managing loans backed by real-world assets. This is helping Tinlake to provide a more efficient and cost-effective lending solution for businesses.Invoice Finance: Invoice Finance is using CassidyAI to automate the process of processing invoices and to provide financing to businesses based on the value of their invoices. This is helping Invoice Finance to provide a more efficient and timely financing solution for businesses.Bondora: Bondora is using CassidyAI to assess the risk of loans and to provide investors with more information about the loans they are considering investing in. This is helping Bondora to provide a more transparent and efficient investment platform for investors.Upstart: Upstart is using CassidyAI to assess the creditworthiness of borrowers and to provide them with more personalized lending terms. This is helping Upstart to provide a more inclusive and affordable lending solution for borrowers.These are just a few examples of how CassidyAI is being used by real businesses to improve their operations and to provide better services to their customers. As CassidyAI continues to develop, it is likely that even more use cases will be discovered.SummaryCassidyAI, a startup in partnership with Neo, OpenAI, and Microsoft, is revolutionizing business productivity through AI-driven automation. Their platform enables businesses to create customized AI-assistants, optimizing productivity and integrating AI across departments. With a no-code approach, CassidyAI caters to various use-cases, including marketing, sales, customer service, engineering, product, and HR. The platform emphasizes data security and transparency while providing a personalized onboarding process. As CassidyAI emerges from stealth mode, it heralds a new era of AI-led business automation, offering businesses the opportunity to enhance productivity and streamline operations.Author BioJulian Melanson is one of the founders of Leap Year Learning. Leap Year Learning is a cutting-edge online school that specializes in teaching creative disciplines and integrating AI tools. We believe that creativity and AI are the keys to a successful future and our courses help equip students with the skills they need to succeed in a continuously evolving world. Our seasoned instructors bring real-world experience to the virtual classroom and our interactive lessons help students reinforce their learning with hands-on activities.No matter your background, from beginners to experts, hobbyists to professionals, Leap Year Learning is here to bring in the future of creativity, productivity, and learning!
Read more
  • 0
  • 0
  • 9462

article-image-creating-file-server-samba
Packt
12 Apr 2013
7 min read
Save for later

Creating a file server (Samba)

Packt
12 Apr 2013
7 min read
(For more resources related to this topic, see here.) The Raspberry Pi with attached file storage functions well as a file server. Such a file server could be used as a central location for sharing files and documents, for storing backups of other computers, and for storing large media files such as photo, music, and video files. This recipe installs and configures samba and samba-common-bin. The Samba software distribution package, samba, contains a server for the SMB (CIFS) protocol used by Windows computers for setting up 'shared drives' or 'shared folders'. The samba-common-bin package contains a small collection of utilities for managing access to shared files. The recipe includes setting a file-sharing password for the user pi and providing read/write access to the files in pi user's home directory. However, it does not set up a new file share or show how to share a USB disk. The next recipe shows how to do that. After completing this recipe, other computers can exchange files with the default user pi. Getting ready The following are the ingredients: A Raspberry Pi with a 5V power supply An installed and configured "official" Raspbian Linux SD card A network connection A client PC connected to the same network as the Raspberry Pi This recipe does not require the desktop GUI and could either be run from the text-based console or from within an LXTerminals. If the Raspberry Pi's Secure Shell server is running and it has a network connection, this recipe can be remotely completed using a Secure Shell client. How to do it... The following are the steps for creating a file server: Log in to the Raspberry Pi either directly or remotely. Execute the following command: apt-get install samba samba-common-bin Download and install samba with the other packages that it depends on. This command needs to be run as a privileged user (use sudo). The package management application aptitude could be used as an alternative to the apt-get command utility for downloading and installing samba and samba-common-bin. In the preceding screenshot, the apt-get command is used to install the samba and samba-common-bin software distribution packages. Execute the following command: nano /etc/samba/smb.conf Edit the samba configuration file. The smb.conf file is protected and needs to be accessed as a privileged user (use sudo). The preceding screenshot starts the nano editor to edit the /etc/samba/smb.conf file. Change the security = user line. Uncomment the line (remove the hash, #, from the beginning of the line). The preceding screenshot of the Samba configuration file shows how to change samba security to use the Raspberry Pi's user accounts. Change the read only = yes line to be read only = no, as shown in the following screenshot: The preceding screenshot shows how to change the Samba configuration file to permit adding new files to user shares (read only = no). Save and exit the nano editor. Execute the following command: /etc/init.d/samba reload Tell the Samba server to reload its configuration file. This command is privileged (use sudo). In the preceding screenshot, the Samba server's configuration file is reloaded with the /etc/init.d/samba command. Execute the following command: smbpasswd –a pi This command needs to be run as a privileged user (use sudo). Enter the password (twice) that will be used for SMB (CIFS) file sharing. The preceding screenshot shows how to add an SMB password for the pi user. The Raspberry Pi is now accessible as a Windows share! From a Windows computer, use Map network drive to mount the Raspberry Pi as a network disk, as follows: The preceding screenshot starts mapping a network drive to the Raspberry Pi on Windows 7. Enter the UNC address raspberrypipi as the network folder. Choose an appropriate drive letter. The example uses the Z: drive. Select Connect using different credentials and click on Finish, as shown in the following screenshot: The preceding screenshot finishes mapping a network drive to the Raspberry Pi. Log in using the newly configured SMB (CIFS) password (from step 7). In the screenshot, a dialog box is displayed for logging in to the Raspberry Pi with the SMB (CIFS) username and password. The Raspberry Pi is now accessible as a Windows share! Only the home directory of the pi user is accessible at this point. The next recipe configures a USB disk for using it as a shared drive. How it works... This recipe begins by installing two software distribution packages – samba and samba-common-bin. This recipe uses the apt-get install command; however, the aptitude package management application could also be used to install software packages. The Samba package contains an implementation of the Server Message Block (SMB) protocol (also known as the Common Internet File System, CIFS). The SMB protocol is used by Microsoft Windows computers for sharing files and printers. The samba-common-bin package contains the smbpasswd command. This command is used to set up user passwords exclusively for using them with the SMB protocol. After the packages are installed, the Samba configuration file /etc/samba/smb.conf is updated. The file is updated to turn on user security and to enable writing files to user home directories. The smbpasswd command is used to add (-a) the pi user to the list of users authorized to share files with the Raspberry Pi using the SMB protocol. The passwords for file sharing are managed separately from the passwords used to log in to the Raspberry Pi either directly or remotely. The smbpasswd command is used to set the password for Samba file sharing. After the password has been added for the pi user, the Raspberry Pi should be accessible from any machine on the local network that is configured for the SMB protocol. The last steps of the recipe configure access to the Raspberry Pi from a Windows 7 PC using a mapped network drive. The UNC name for the file share, raspberrypipi, could also be used to access the share directly from Windows Explorer. There's more... This is a very simple configuration for sharing files. It enables file sharing for users with a login to the Raspberry Pi. However, it only permits the files in the user home directories to be shared. The next recipe describes how to add a new a file share. In addition to the SMB protocol server, smbd, the Samba software distribution package also contains a NetBIOS name server, nmbd. The NetBIOS name server provides naming services to computers using the SMB protocol. The nmbd server broadcasts the configured name of the Raspberry Pi, raspberrypi, to other computers on the local network. In addition to file sharing, a Samba server could also be used as a Primary Domain Controller (PDC) — a central network server that is used to provide logins and security for all computers on a LAN. More information on using the Samba package as a PDC can be found on the links given next. See Also Samba (software) http://en.wikipedia.org/wiki/Samba_(software) A Wikipedia article on the Samba software suite. nmbd - NetBIOS over IP naming service http://manpages.debian.net/cgi-bin/man.cgi?query=nmbd The Debian man page for nmbd. samba – a Windows SMB/CIFS file server for UNIX http://manpages.debian.net/cgi-bin/man.cgi?query=samba The Debian man page for samba. smb.conf - the configuration file for the Samba suite http://manpages.debian.net/cgi-bin/man.cgi?query=smb.conf The Debian man page for smb.conf. smbd - server to provide SMB/CIFS services to clients http://manpages.debian.net/cgi-bin/man.cgi?query=smbd The Debian man page for smbd. smbpasswd - change a user's SMB password http://manpages.debian.net/cgi-bin/man.cgi?query=smbpasswd The Debian man page for smbpasswd. System initialization http://www.debian.org/doc/manuals/debian-reference/ch04.en.html The Debian Reference Manual article on system initialization. Samba.org http://www.samba.org The Samba software website. Resources for Article : Further resources on this subject: Using PVR with Raspbmc [Article] Our First Project – A Basic Thermometer [Article] Instant Minecraft Designs – Building a Tudor-style house [Article]
Read more
  • 0
  • 0
  • 9457

article-image-modules
Packt
08 Mar 2013
6 min read
Save for later

Modules

Packt
08 Mar 2013
6 min read
(For more resources related to this topic, see here.) We are going to try mastering modules which will help us break up our application into sensible components. Our configuration file for modules is given as follows: var guidebookConfig = function($routeProvider) { $routeProvider .when('/', { controller: 'ChaptersController', templateUrl: 'view/chapters.html' }) .when('/chapter/:chapterId', { controller: 'ChaptersController', templateUrl: 'view/chapters.html' }) .when('/addNote/:chapterId', { controller: 'AddNoteController', templateUrl: 'view/addNote.html' }) .when('/deleteNote/:chapterId/:noteId', { controller: 'DeleteNoteController', templateUrl: 'view/addNote.html' }) ; }; var Guidebook = angular.module('Guidebook', []). config(guidebookConfig); The last line is where we define our Guidebook module. This creates a namespace for our application. Look at how we defined the add and delete note controllers: Guidebook.controller('AddNoteController', function ($scope, $location, $routeParams, NoteModel) { var chapterId = $routeParams.chapterId; $scope.cancel = function() { $location.path('/chapter/' + chapterId); } $scope.createNote = function() { NoteModel.addNote(chapterId, $scope.note.content); $location.path('/chapter/' + chapterId); } } ); Guidebook.controller('DeleteNoteController', function ($scope, $location, $routeParams, NoteModel) { var chapterId = $routeParams.chapterId; NoteModel.deleteNote(chapterId, $routeParams.noteId); $location.path('/chapter/' + chapterId); } ); Since Guidebook is a module, we're really making a call to module.controller() to define our controller. We also called Guidebook.service(), which is really just module.service(), to define our models. One advantage of defining controllers, models, and other components as part of a module is that it groups them together under a common name. This way, if we have multiple applications on the same page, or content from another framework, it's easy to remember which components belong to which application. The second advantage of defining components as part of a module is that AngularJS will do some heavy lifting for us. Take our NoteModel, for instance. We defined it as a service by calling module.service(). AngularJS provides some extra functionality to services within a module. One example of that extra functionality is dependency injection. This is why in our DeleteNoteController, we can include our note model simply by asking for it in the controller's function: Guidebook.controller('DeleteNoteController', function ($scope, $location, $routeParams, NoteModel) { var chapterId = $routeParams.chapterId; NoteModel.deleteNote(chapterId, $routeParams.noteId); $location.path('/chapter/' + chapterId); } ); This only works because we registered both DeleteNoteController and NoteModel as parts of the same module. Let's talk a little more about NoteModel. When we define controllers on our module, we call module.controller(). For our models, we called module.service(). Why isn't there a module.model()? Well, it turns out models are a good bit more complicated than controllers. In our Guidebook application, our models were relatively simple, but what if we were mapping our models to some external API, or a full- fledged relational database? Because there are so many different types of models with vastly different levels of complexity, AngularJS provides three ways to define a model: as a service, as a factory, and as a provider. We'll now see how we define a service in our NoteModel: Guidebook.service('NoteModel', function() { this.getNotesForChapter = function(chapterId) { ... }; this.addNote = function(chapterId, noteContent) { ... }; this.deleteNote = function(chapterId, noteId) { ... }; }); It turns out this is the simplest type of model. We're simply defining an object with a number of functions that our controllers can call. This is all we needed in our case, but what if we were doing something a little more complicated? Let's pretend that instead of using HTML5 local storage to store and retrieve our note data, we're getting it from a web server somewhere. We'll need to add some logic to set up and manage the connection with that server. The service definition can help us a little here with the setup logic; we're returning a function, so we could easily add some initialization logic. When we get into managing the connection, though, things get a little messy. We'll probably want a way to refresh the connection, in case it drops. Where would that go? With our service definition, our only option is to add it as a function like we have for getNotesForChapter(). This is really hacky; we're now exposing how the model is implemented to the controller, and worse, we would be allowing the controller to refresh the connection. In this case, we would be better off using a factory. Here's what our NoteModel would look like if we had defined it as a factory: Guidebook.factory('NoteModel', function() { return { getNotesForChapter: function(chapterId) { ... }, addNote: function(chapterId, noteContent) { ... }, deleteNote: function(chapterId, noteId) { ... } }; }); Now we can add more complex initialization logic to our model. We could define a few functions for managing the connection privately in our factory initialization, and give our data methods references to them. The following is what that might look like: Guidebook.factory('NoteModel', function() { var refreshConnection = function() { ... }; return { getNotesForChapter: function(chapterId) { ... refreshConnection(); ... }, addNote: function(chapterId, noteContent) { ... refreshConnection(); ... }, deleteNote: function(chapterId, noteId) { ... refreshConnection(); ... } }; }); Isn't that so much cleaner? We've once again kept our model's internal workings completely separate from our controller. Let's get even crazier. What if we backed our models with a complex database server with multiple endpoints? How could we configure which endpoint to use? With a service or a factory, we could initialize this in the model. But what if we have a whole bunch of models? Do we really want to hardcode that logic into each one individually? At this point, the model shouldn't be making this decision. We want to choose our endpoints in a configuration file somewhere. Reading from a configuration file in either a service or a factory will be awkward. Models should focus solely on storing and retrieving data, not messing around with configuration updates. Provider to the rescue! If we define our NoteModel as a provider, we can do all kinds of configuration from some neatly abstracted configuration file. Here's how our NoteModel looks if we convert it into a provider: Guidebook.provider('NoteModel', function() { this.endpoint = 'defaultEndpoint'; this.setEndpoint = function(newEndpoint) { this.endpoint = newEndpoint; }; this.$get = function() { var endpoint = this.endpoint; var refreshConnection = function() { // reconnect to endpoint }; return { getNotesForChapter: function(chapterId) { ... refreshConnection(); ... }, addNote: function(chapterId, noteContent) { ... refreshConnection(); ... }, deleteNote: function(chapterId, noteId) { ... refreshConnection(); ... } }; }; }); Now if we add a configuration file to our application, we can configure the endpoint from outside the model: Guidebook.config(function(NoteModelProvider) { NoteModelProvider.setEndpoint('anEndpoint'); }); Providers give us a very powerful architecture. If we have several models, and we have several endpoints, we can configure all of them in one single configuration file. This is ideal, as our models remain single-purpose and our controllers still have no knowledge of the internals of the models they depend on. Summary Thus we saw in this article modules provide an easy, flexible way to create components in AngularJS. We've seen three different ways to define a model, and we've discussed the benefits of using a module to create an application namespace. Resources for Article : Further resources on this subject: Framework Comparison: Backbase AJAX framework Vs Other Similar Framework (Part 1) [Article] Getting Started With Spring MVC - Developing the MVC components [Article] ASP.NET MVC Framework [Article]
Read more
  • 0
  • 0
  • 9456

article-image-memory-management
Packt
17 Mar 2016
18 min read
Save for later

Memory Management

Packt
17 Mar 2016
18 min read
In this article by Andrew Wagner, author of the book Learning Swift - Second Edition, we will see how to manage memory. As we know that when using an app, not much is worse than it being slow and unresponsive. Computer users have come to expect every piece of software to respond immediately to every interaction. Even the most feature-rich app will be ruined if it is unpleasant to use, because it won't manage the device's resources effectively. Also, with the growing popularity of mobile computers and devices, it is more important than ever to write software that efficiently uses battery power. One of the aspects of writing software that has the largest impact on both responsiveness and battery power is memory management. (For more resources related to this topic, see here.) In this article, we will discuss techniques specific to Swift that allow us to manage memoryin order to ensure that our code remains responsive and minimizes its effect on battery life. We will do so by covering: Value types versus reference types Automatic reference counting Value types versus reference types All variables and constants in Swift are stored in memory. In fact, unless you explicitly write data to the filesystem, everything you create is going to be in memory. In Swift, there are two different types of categories. These two categories are value types and reference types. The only way they differ is how they behave when they are assigned to new variables, passed into methods, or captured in closures. Essentially, they only differ when you try to assign a new variable or constant to the value of an existing variable or constant. A value type is always copied when being assigned somewhere new, while a reference type is not. Before we look at what exactly this means in more detail, let's go over how we determine whether a type is a value type or a reference type. Determining between a value type or reference type A value type is any type that is defined either as a structure or an enumeration, while all classes are reference types. This is easy to determine for your own custom types based on how you declared them. Beyond this, all of the built-in types for Swift, such as strings, arrays, and dictionaries, are value types. If you are ever uncertain, you can test any type you want in a playground to see whether its behavior is consistent with a value type or a reference type. The simplest behavior to check is what happens on assignment. Behaviour on assignment When a value type is reassigned, it is copied so that afterwards, each variable or constant holds a distinct value that can be changed independently. Let's look at a simple example using a string: var value1 = "Hello" var value2 = value1 value1 += " World!" print(value1) // "Hello World!" print(value2) // "Hello" As you can see, when value2 is set to value1, a copy is created. That makes it so that when we append "World!" to value1, value2 remains unchanged as "Hello". We can visualize them as two completely separate entities: On the other hand, let's look at what happens with a reference type: class Person { var name: String init(name: String) { self.name = name } } var reference1 = Person(name: "Kai") var reference2 = reference1 reference1.name = "Naya" print(reference1.name) // "Naya" print(reference2.name) // "Naya" As you can see, when we changed the name of reference1, reference2 was also changed. So why is this? As the name implies, reference types are simply references to an instance. When you assign a reference to another variable or constant, both are actually referring to the exact same instance. We can visualize this as two separate objects referencing the same instance: In the real world, this would be like two kids sharing a toy. Both can play with the toy but if one breaks the toy, it is broken for both kids. However, it is important to realize that if you assign a reference type to a new value, it does not change the value it was originally referencing: reference2 = Person(name: "Kai") print(reference1.name) // "Naya" print(reference2.name) // "Kai" As you can see, we assigned reference2 to an entirely different Person instance, so they can now be manipulated independently. We could then visualize this as two separate references to two separate instances: This would be like buying a new toy for one of the kids. This actually shows you that a reference type is really a special version of a value type. The difference is that a reference type is not itself an instance of any type. It is simply a reference to an instance. You can copy the reference so that you then have two variables referencing the same instance, or you can give a variable a completely new reference to a new instance. With reference types, there is an extra layer of indirection based on the sharing of instances between multiple variables. Now that we know this, the simplest way to verify whether a type is a value type or a reference type is to check its behavior when it is being assigned. If the second value is changed when you modify the first value, it means that whatever type you are testing is a reference type. Behavior on input Another place where the behavior of a value type differs from that of a reference type is when passing them into functions and methods. However, the behavior is very simple to remember if you look at passing a variable or constant into a function as just another assignment. This means that when you pass a value type into a function, it is copied, while a reference type still shares the same value: func setNameOfPerson(person: Person, var to name: String) { person.name = name name = "Other Name" } Here, we have defined a function that takes both a reference type,Person, and a value type,String. When we update the person's data within the function, the person we passed in is also changed: var person = Person(name: "Sarah") var newName = "Jamison" setNameOfPerson(person, to: newName) print(person.name) // "Jamison" print(newName) // "Jamison" However, when we change the string within the function, the string passed in remains unchanged. The place where things get a little more complicated is with in-out parameters. An in-out parameter is actually a reference to the passed-in instance. This means that it will treat a value type as if it were a reference type: func updateString(inout string: String) { string = "Other String" } var someString = "Some String" updateString(&someString) print(someString) // "Other String" As you can see, when we changed the in-out version of string within the function, it also changed the someString variable outside of the function just as if it were a reference type. If we remember that a reference type is just a special version of a value type where the value is a reference, we can infer what will be possible with an in-out version of a reference type. When we define an in-out reference type, we actually have a reference to a reference; that reference is then the one that is pointing to a reference. We can visualize the difference between an in-out value type and an in-out reference type like this: If we simply change the value of this variable, we will get the same behavior as if it were not an in-out parameter. However, by making it an in-out parameter, we can also change where the inner reference is referring to: func updatePerson(inout insidePerson: Person) { insidePerson.name = "New Name" insidePerson = Person(name: "New Person") } var person2 = person updatePerson(&person) print(person.name) // "New Person" print(person2.name) // "New Name" We start out by creating a second reference—person2—to the same instance as the person variable that currently has the name Jamison from before. After that, we pass the original person variable into our updatePerson method and have this: In this method, we first change the name of the existing person to a new name. We can see in the output that the name of person2 is also changed because both insidePerson inside the function and person2 are still referencing the same instance: However, we then also assign insidePerson to a completely new instance of the Person reference type. This results in person and person2 outside of the function pointing at two completely different instances of Person, leaving the name of person2 to be New Name and updating the name of person to New Person: Here, by defining insidePerson as an in-out parameter, we were able to change where the passed-in variable was referencing to. This can help us visualize all of the different options as one type pointing to another. At any point, any of these arrows can be pointed to something new using an assignment, and the instance can always be accessed through the references. Closure capture behaviour The last behavior we have to worry about is when variables are captured within closures. Closures can actually use variables that were defined in the same scope as the closure itself: var nameToPrint = "Kai" var printName = { print(nameToPrint) } printName() // "Kai" This is very different from the normal parameters that we have seen before. We don't actually specify nameToPrint as a parameter, nor do we pass it in when calling the method. Instead, the closure is capturing the nameToPrint variable that is defined before it. These types of captures act similarly to in-out parameters in functions. When a value type is captured, it can be changed, and this will change the original value as well: var outsideName = "Kai" var setName = { outsideName = "New Name" } print(outsideName) // "Kai" setName() print(outsideName) // "New Name" As you can see, outsideName was changed after the closure was called. This is exactly like an in-out parameter. When a reference type is captured, any changes will also be applied to the outside version of the variable: var outsidePerson = Person(name: "Kai") var setPersonName = { outsidePerson.name = "New Name" } print(outsidePerson.name) // "Kai" setPersonName() print(outsidePerson.name) // "New Name" This is also exactly like an in-out parameter. The only place where capture behavior differs from an in-out parameter is that you cannot reassign the captured reference value to a new instance. If you try, the compiler will produce an error. This means that it is safe to treat captured variables as in-out parameters because the compiler will stop you in the only place where they differ. The other part of closure capture that we need to keep in mind is that changing the captured value after the closure is defined will still affect the value within the closure. We could take advantage of this in order to use the printName closure we defined previously to print any name: nameToPrint = "Kai" printName() // Kai nameToPrint = "New Name" printName() // "New Name" As you can see, we can change what printName prints out by changing the value of nameToPrint. This behavior is actually very hard to track down when it happens accidently, so it is usually a good idea to avoid capturing variables in closures whenever possible. In this case, we were taking advantage of the behavior, but more often than not, it will cause bugs. Here, it would be better to just pass what we want to print as an argument. Another way to avoid this behavior is to use a feature called capture lists. With this, you can specify variables that you want to capture by copying them: nameToPrint = "Original Name" var printNameWithCapture = { [nameToPrint] in print(nameToPrint) } printNameWithCapture() // "Original Name" nameToPrint = "New Name" printNameWithCapture() // "Original Name" A capture list is defined at the beginning of a closure before any parameters. It is a comma-separated list of all the variables being captured that we want to copy within square brackets. In this case, we requested that nameToPrint be copied so that when we change it later, it does not affect the value that is printed out. Automatic reference counting Now that we understand the different ways in which data is represented in Swift, we can look into how we can manage memory better. Every instance we create takes up memory. Naturally, it wouldn't make sense to keep all data around forever. Swift needs to be able to free up memory to be used for other purposes once our program doesn't need it anymore. This is the key to managing memory in our apps. We need to make sure that Swift can free up all of the memory that we no longer need as soon as possible. The way that Swift knows it can free up memory is when the code can no longer access an instance. If there is no longer any variable or constant referencing an instance, it can be repurposed for another instance. This is called "freeing the memory" or "deleting the object". Since value types are always copied when they are reassigned or passed into functions, they can be immediately deleted once they go out of scope. We can look at a simple example to get the full picture: func printSomething() { let something = "Hello World!" print(something) } Here we have a very simple function that prints out "Hello World!". When printSomething is called, something is assigned to a new instance of String with the value "Hello World!". After print is called, the function exits, and something is therefore no longer in scope. At that point, the memory being taken up by something can be freed. While this is very simple, reference types are much more complex. At a high level, an instance of a reference type is deleted at the point when there are no longer any references to the instance in scope anymore. This is relatively straightforward to understand but it gets more complex in the details. The Swift feature that manages this is called automatic reference counting, or ARC for short. Object relationships The key to ARC is that every object has relationships with one or more variables. This can be extended to include the idea that all objects have a relationship with other objects. For example, a car object would contain objects for its four tires, engine, and so on. It would also have a relationship with its manufacturer, dealership, and owner. ARC uses these relationships to determine when an object can be deleted. In Swift, there are three different types of relationships: strong, weak, and unowned. Strong The first, and default, type of relationship is a strong relationship. It says that a variable requires that the instance it is referring to must always exist as long as the variable is still in scope. This is the only behavior available for value types. When an instance no longer has any strong relationships to it, it will be deleted. A great example of this type of relationship is with a car, which must have a steering wheel: class SteeringWheel {} class Car { var steeringWheel: SteeringWheel init(steeringWheel: SteeringWheel) { self.steeringWheel = steeringWheel } } By default, the steeringWheel property has a strong relationship with the SteeringWheel instance it is initialized with. Conceptually, this means that the car itself has a strong relationship with the steering wheel. As long as the car exists, it must have a relationship with a steering wheel. Since steeringWheel is declared as a variable, we could change the steering wheel of the car, which would remove the old strong relationship and add a new one; however, a strong relationship will always exist. If we were to create a new instance of Car and store it in a variable, that variable would have a strong relationship to the car: let wheel = SteeringWheel() let car = Car(steeringWheel: wheel) Let's break down all of the relationships in this code. First, we create the wheel constant and assign it to a new instance of SteeringWheel. This sets up a strong relationship from wheel to the new instance. We do the same thing with the car constant, but this time, we also pass in the wheel constant to the initializer. Now, not only does car have a strong relationship with the new Car instance, but the Car initializer also creates a strong relationship from the steeringWheel property and with the same instance as the wheel constant: So what does this relationship graph mean for memory management? At this time, the Car instance has one strong relationship: the car constant, and the SteeringWheel instance has two strong relationships: the wheel constant and the steeringWheel property of the Car instance. This means that the Car instance will be deleted as soon as the car constant goes out of scope. On the other hand, the SteeringWheel instance will only be deleted after both the wheel constant goes out of scope and the Car instance is deleted. You can envision a strong reference counter on every instance in your program. Every time a strong relationship is set up to an instance, the counter goes up. Every time an object strongly referencing it gets deleted, the counter goes down. If that counter ever goes back to zero, the instance is deleted. The other important thing to realize is that all relationships are only in one direction. Just because the Car instance has a strong relationship with the SteeringWheel instance does not mean the SteeringWheel instance has any relationship back. You could add your own relationship back by adding a car property to the SteeringWheel class, but you have to be careful when doing this, as we will see in the strong reference cycle section coming up. Weak The next type of relationship in Swift is a weak relationship. It allows one object to reference another without enforcing that it always exists. A weak relationship does not contribute to the reference counter of an instance, which means that the addition of a weak relationship does not increase the counter, nor does it decrease the counter when removed. Since a weak relationship cannot guarantee that it will always exist, it must always be defined as an optional. A weak relationship is defined using the weak keyword before the variable declaration: class SteeringWheel { weak var car: Car? } This allows a SteeringWheel to have a car assigned to it, without enforcing that the car never be deleted. The car initializer can then assign this backwards reference to itself: class Car { var steeringWheel: SteeringWheel init(steeringWheel: SteeringWheel) { self.steeringWheel = steeringWheel self.steeringWheel.car = self } } If the car is ever deleted, the car property of SteeringWheel will automatically be set to null. This allows us to gracefully handle the scenario in which a weak relationship refers to an instance that has been deleted. Unowned The final type of relationship is an unowned relationship. This relationship is almost identical to a weak relationship. It also allows one object to reference another without contributing to the strong reference count. The only difference is that an unowned relationship does not need to be declared as optional, and it uses the unowned keyword instead of weak. It acts very similarly to an implicitly unwrapped optional. You can interact with an unowned relationship as if it were a strong relationship, but if the unowned instance has been deleted and you try to access it, your entire program will crash. This means that you should only use unowned relationships in scenarios where the unowned object will never actually be deleted while the primary object still exists. You may ask then, "Why would we not always use a strong relationship instead?" The answer is that sometimes unowned or weak references are needed to break something called a strong reference cycle. Summary Memory management is often considered difficult to understand, but when you break it down, you can see that it is relatively straightforward. In this chapter, we saw that in Swift, there are value types and reference types, which are critical to understanding how we can reduce memory usage and eliminate memory leaks. Memory leaks are created when an object has a strong reference to itself through a third party, which is called a strong reference cycle. We must also be careful that we keep at least one strongreference to every object that we want to stay around, or we may lose them prematurely. With practice, you will get better at both preventing and fixing memory problems. You will write streamlined apps that keep your users' computers running smoothly. Resources for Article: Further resources on this subject: Concurrency and Parallelism with Swift 2[article] Your First Swift 2 Project[article] Exploring Swift[article]
Read more
  • 0
  • 0
  • 9455
article-image-transformation
Packt
20 Dec 2013
23 min read
Save for later

Apache Camel: Transformation

Packt
20 Dec 2013
23 min read
(For more resources related to this topic, see here.) The latest version of the example code for this article can be found at http://github.com/CamelCookbook/camel-cookbook-examples. You can also download the example code files for all Packt books you have purchased from your account at https://www.packtpub.com. If you purchased this book elsewhere, you can visit https://www.packtpub.com/books/content/support and register to have the files e-mailed directly to you. In this article we will explore a number of ways in which Camel performs message content transformation: Let us first look at some important concepts regarding transformation of messages in Camel: Using the transform statement. This allows you to reference Camel Expression Language code within the route to do message transformations. Calling a templating component, such as Camel's XSLT or Velocity template style components. This will typically reference an external template resource that is used in transforming your message. Calling a Java method (for example, beanref), defined by you, within a Camel route to perform the transformation. This is a special case processor that can invoke any referenced Java object method. Camel's Type Converter capability that can automatically cast data from one type to another transparently within your Camel route. This capability is extensible, so you can add your own Type Converters. Camel's Data Format capability that allows us to use built-in, or add our own, higher order message format converters. A Camel Data Format goes beyond simple data type converters, which handle simple data type translations such as String to int, or File to String. Data Formats are used to translate between a low-level representation (XML) and a high-level one (Java objects). Other examples include encrypting/decrypting data, and compressing/decompressing data. For more, see http://camel.apache.org/data-format.html. A number of Camel architectural concepts are used throughout this article. Full details can be found at the Apache Camel website at http://camel.apache.org. The code for this article is contained within the camel-cookbook-transformation module of the examples. Transforming using a Simple Expression When you want to transform a message in a relatively straightforward way, you use Camel's transform statement along with one of the Expression Languages provided by the framework. For example, Camel's Simple Expression Language provides you with a quick, inline mechanism for straightforward transformations. This recipe will show you how to use Camel's Simple Expression Language to transform the message body. Getting ready The Java code for this recipe is located in the org.camelcookbook.transformation.simple package. Spring XML files are located under src/main/resources/META-INF/spring and are prefixed with simple. How to do it... In a Camel route, use a transform DSL statement containing the Expression Language code to do your transformation. In the XML DSL, this is written as follows: <route> <from uri="direct:start"/> <transform> <simple>Hello ${body}</simple> </transform> </route> In the Java DSL, the same route is expressed as: from("direct:start") .transform(simple("Hello ${body}")); In this example, the message transformation prefixes the incoming message with the phrase Hello using the Simple Expression Language. The processing step after the transform statement will see the transformed message content in the body of the exchange. How it works... Camel's Simple Expression Language is quite good at manipulating the String content through its access to all aspects of the message being processed, through its rich String and logical operators. The result of your Simple Expression becomes the new message body after the transform step. This includes predicates such as using Simple's logical operators, to evaluate a true or false condition; the results of that Boolean operation become the new message body containing a String: "true" or "false". The advantage of using a distinct transform step within a route, as opposed to embedding it within a processor, is that the logic is clearly visible to other programmers. Ensure that the expression embedded within your route is kept simple so as to not distract the next developer from the overall purpose of the integration. It is best to move more complex (or just lengthy) transformation logic into its own subroute, and invoke it using direct: or seda:. There's more... The transform statement will work with any Expression Language available in Camel, so if you need more powerful message processing capabilities you can leverage scripting languages such as Groovy or JavaScript (among many others) as well. The Transforming inline with XQuery recipe will show you how to use the XQuery Expression Language to do transformations on XML messages. See also Message Translator: http://camel.apache.org/message-translator.html Camel Expression capabilities: http://camel.apache.org/expression.html Camel Simple Expression Language: http://camel.apache.org/simple.html Languages supported by Camel: http://camel.apache.org/languages.html The Transforming inline with XQuery recipe   Transforming inline with XQuery Camel supports the use of Camel's XQuery Expression Language along with the transform statement as a quick and easy way to transform an XML message within a route. This recipe will show you how to use an XQuery Expression to do in-route XML transformation. Getting ready The Java code for this recipe is located in the org.camelcookbook.transformation.xquery package. Spring XML files are located under src/main/resources/META-INF/spring and prefixed with xquery. To use the XQuery Expression Language, you need to add a dependency element for the camel-saxon library, which provides the implementation for the XQuery Expression Language. Add the following to the dependencies section of your Maven POM: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-saxon</artifactId> <version>${camel-version}</version> </dependency>   How to do it... In the Camel route, specify a transform statement followed by the XQuery Expression Language code to do your transformation. In the XML DSL, this is written as: <route> <from uri="direct:start"/> <transform> <xquery> <books>{ for $x in /bookstore/book where $x/price>30 order by $x/title return $x/title }</books> </xquery> </transform> </route> When using the XML DSL, remember to XML encode the XQuery embedded XML elements. Therefore, < becomes &lt; and > becomes &gt;. In the Java DSL, the same route is expressed as: from("direct:start") .transform(xquery("<books>{ for $x in /bookstore/book " + "where $x/price>30 order by $x/title " + "return $x/title }</books>")); Feed the following input XML message through the transformation: <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="PROGRAMMING"> <title lang="en">Apache Camel Developer's Cookbook</title> <author>Scott Cranton</author> <author>Jakub Korab</author> <year>2013</year> <price>49.99</price> </book> <book category="WEB"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore> The resulting message will be: <books> <title lang="en">Apache Camel Developer's Cookbook</title> <title lang="en">Learning XML</title> </books> The processing step after the transform statement will see the transformed message content in the body of the exchange. How it works... Camel's XQuery Expression Language is a good way to inline XML transformation code within your route. The result of the XQuery Expression becomes the new message body after the transform step. All of the message's body, headers, and properties are made available to the XQuery Processor, so you can reference them directly within your XQuery statement. This provides you with a powerful mechanism for transforming XML messages. If you are more comfortable with XSLT, take a look at the Transforming with XSLT recipe. In-lining the transformation within your integration route can sometimes be an advantage as you can clearly see what is being changed. However, when the transformation expression becomes so complex that it starts to overwhelm the integration route, you may want to consider moving the transformation expression outside of the route. See the Transforming using a Simple Expression recipe for another inline transformation example, and see the Transforming with XSLT recipe for an example of externalizing your transformation. You can fetch the XQuery Expression from an external file using Camel's resource reference syntax. To reference an XQuery file on the classpath you can specify: <transform> <xquery>resource:classpath:/path/to/myxquery.xml</xquery> </transform> This is equivalent to using XQuery as an endpoint: <to uri="xquery:classpath:/path/to/myxquery.xml"/>   There's more... The XQuery Expression Language allows you to pass in headers associated with the message. These will show up as XQuery variables that can be referenced within your XQuery statements. Consider, from the previous example, to allow the value of the books that are filtered to be passed in with the message body, that is, parameterize the XQuery, you can modify the XQuery statement as follows: <transform> <xquery> declare variable $in.headers.myParamValue as xs:integer external; <books value='{$in.headers.myParamValue}'&gt;{ for $x in /bookstore/book where $x/price>$in.headers.myParamValue order by $x/title return $x/title }&lt;/books&gt; </xquery> </transform> Message headers will be associated with an XQuery variable called in.headers.<name of header>. To use this in your XQuery, you need to explicitly declare an external variable of the same name and XML Schema (xs:) type as the value of the message header. The transform statement will work with any Expression Language enabled within Camel, so if you need more powerful message processing capabilities you can leverage scripting languages such as Groovy or JavaScript (among many others) as well. The Transforming using a Simple Expression recipe will show you how to use the Simple Expression Language to do transformations on String messages. See also Message Translator: http://camel.apache.org/message-translator.html Camel Expression capabilities: http://camel.apache.org/expression.html Camel XQuery Expression Language: http://camel.apache.org/xquery.html XQuery language: http://www.w3.org/XML/Query/ Languages supported by Camel: http://camel.apache.org/languages.html The Transforming with XSLT recipe The Transforming using a Simple Expression recipe   Transforming with XSLT When you want to transform an XML message using XSLT, use Camel's XSLT Component. This is similar to the Transforming inline with XQuery recipe except that there is no XSLT Expression Language, so it can only be used as an endpoint. This recipe will show you how to transform a message using an external XSLT resource. Getting ready The Java code for this recipe is located in the org.camelcookbook.transformation.xslt package. Spring XML files are located under src/main/resources/META-INF/spring and prefixed with xslt. How to do it... In a Camel route, add the xslt processor step into the route at the point where you want the XSLT transformation to occur. The XSLT file must be referenced as an external resource, and depending on where the file is located, prefixed with either classpath:(default if not using a prefix), file:, or http:. In the XML DSL, this is written as: <route> <from uri="direct:start"/> <to uri="xslt:book.xslt"/> </route> In the Java DSL, the same route is expressed as: from("direct:start") .to("xslt:book.xslt"); The next processing step in the route will see the transformed message content in the body of the exchange. How it works... The following example shows how the preceding steps will process an XML file. Consider the following input XML message: <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="PROGRAMMING"> <title lang="en">Apache Camel Developer's Cookbook</title> <author>Scott Cranton</author> <author>Jakub Korab</author> <year>2013</year> <price>49.99</price> </book> <book category="WEB"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore> Process this with the following XSLT contained in books.xslt: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" > <xsl:output omit-xml-declaration="yes"/> <xsl:template match="/"> <books> <xsl:apply-templates select="/bookstore/book/title[../price>30]"> <xsl:sort select="."/> </xsl:apply-templates> </books> </xsl:template> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> </xsl:stylesheet> The result will appear as follows: <books> <title lang="en">Apache Camel Developer's Cookbook</title> <title lang="en">Learning XML</title> </books> The Camel XSLT Processor internally runs the message body through a registered Java XML transformer using the XSLT file referenced by the endpoint. This processor uses Camel's Type Converter capabilities to convert the input message body type to one of the supported XML source models in the following order of priority: StAXSource (off by default; this can be enabled by setting allowStAX=true on the endpoint URI) SAXSource StreamSource DOMSource Camel's Type Converter can convert from most input types (String, File, byte[], and so on) to one of the XML source types for most XML content loaded through other Camel endpoints with no extra work on your part. The output data type for the message is, by default, a String, and is configurable using the output parameter on the xslt endpoint URI. There's more... The XSLT Processor passes in headers, properties, and parameters associated with the message. These will show up as XSLT parameters that can be referenced within your XSLT statements. You can pass in the names of the books as parameters to the XSLT template; to do so, modify the previous XLST as follows: <xsl:param name="myParamValue"/> <xsl:template match="/"> <books> <xsl:attribute name="value"> <xsl:value-of select="$myParamValue"/> </xsl:attribute> <xsl:apply-templates select="/bookstore/book/title[../price>$myParamValue]"> <xsl:sort select="."/> </xsl:apply-templates> </books> </xsl:template> The Exchange instance will be associated with a parameter called exchange; the IN message with a parameter called in; and the message headers, properties, and parameters will be associated XSLT parameters with the same name. To use these in your XSLT, you need to explicitly declare a parameter of the same name in your XSLT file. In the previous example, it is possible to use either a message header or exchange property called myParamValue. See also Message Translator: http://camel.apache.org/message-translator.html Camel XSLT Component: http://camel.apache.org/xslt Camel Type Converter: http://camel.apache.org/type-converter.html XSL working group: http://www.w3.org/Style/XSL/ The Transforming inline with XQuery recipe   Transforming from Java to XML with JAXB Camel's JAXB Component is one of a number of components that can be used to convert your XML data back and forth from Java objects. It provides a Camel Data Format that allows you to use JAXB annotated Java classes, and then marshal (Java to XML) or unmarshal (XML to Java) your data. JAXB is a Java standard for translating between XML data and Java that is used by creating annotated Java classes that bind, or map, to your XML data schema. The framework takes care of the rest. This recipe will show you how to use the JAXB Camel Data Format to convert back and forth from Java to XML. Getting ready The Java code for this recipe is located in the org.camelcookbook.transformation.jaxb package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with jaxb. To use Camel's JAXB Component, you need to add a dependency element for the camel-jaxb library, which provides the implementation for the JAXB Data Format. Add the following to the dependencies section of your Maven POM: <dependency> lt;groupId>org.apache.camel</groupId> <artifactId>camel-jaxb</artifactId> <version>${camel-version}</version> lt;/dependency>   How to do it... The main steps for converting between Java and XML are as follows: Given a JAXB annotated model, reference that model within a named Camel Data Format. Use that named Data Format within your Camel route using the marshal and unmarshal DSL statements. Create an annotated Java model using standard JAXB annotations. There are a number of external tools that can automate this creation from existing XML or XSD (XML Schema) files: @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "title", "author", "year", "price" } ) @XmlRootElement(name = "book") public class Book { @XmlElement(required = true) protected Book.Title title; @XmlElement(required = true) protected List<String> author; protected int year; protected double price; // getters and setters } Instantiate a JAXB Data Format within your Camel route that refers to the Java package(s) containing your JAXB annotated classes. In the XML DSL, this is written as: <camelContext > <dataFormats> <jaxb id="myJaxb" contextPath="org.camelcookbook .transformation.myschema"/> </dataFormats> <!-- route definitions here --> </camelContext> In the Java DSL, the Data Format is defined as: public class JaxbRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { DataFormat myJaxb= new JaxbDataFormat( "org.camelcookbook.transformation.myschema"); // route definitions here } } Reference the Data Format within your route, choosing marshal(Java to XML) or unmarshal(XML to Java) as appropriate. In the XML DSL, this routing logic is written as: <route> <from uri="direct:unmarshal"/> <unmarshal ref="myJaxb"/> </route> In the Java DSL, this is expressed as: from("direct:unmarshal").unmarshal(myJaxb);   How it works... Using Camel JAXB to translate your XML data back and forth to Java makes it much easier for the Java processors defined later on in your route to do custom message processing. This is useful when the built-in XML translators (for example, XSLT or XQuery) are not enough, or you just want to call existing Java code. Camel JAXB eliminates the boilerplate code from your integration flows by providing a wrapper around the standard JAXB mechanisms for instantiating the Java binding for the XML data. There's more... Camel JAXB works just fine with existing JAXB tooling like the maven-jaxb2-plugin plugin, which can automatically create JAXB-annotated Java classes from an XML Schema (XSD). See also Camel JAXB: http://camel.apache.org/jaxb.html Available Data Formats: http://camel.apache.org/data-format.html JAXB Specification: http://jcp.org/en/jsr/detail?id=222   Transforming from Java to JSON Camel's JSON Component is used when you need to convert your JSON data back and forth from Java. It provides a Camel Data Format that, without any requirement for an annotated Java class, allows you to marshal (Java to JSON) or unmarshal (JSON to Java) your data. There is only one step to using Camel JSON to marshal and unmarshal XML data. Within your Camel route, insert the marshal(Java to JSON), or unmarshal(JSON to Java) statement, and configure it to use the JSON Data Format. This recipe will show you how to use the camel-xstream library to convert from Java to JSON, and back. Getting ready The Java code for this recipe is located in the org.camelcookbook.transformation.json package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with json. To use Camel's JSON Component, you need to add a dependency element for the camel-xstream library, which provides an implementation for the JSON Data Format using the XStream library. Add the following to the dependencies section of your Maven POM: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-xstream</artifactId> <version>${camel-version}</version> </dependency>   How to do it... Reference the Data Format within your route, choosing the marshal (Java to JSON), or unmarshal (JSON to Java) statement, as appropriate: In the XML DSL, this is written as follows: <route> <from uri="direct:marshal"/> <marshal> <json/> </marshal> <to uri="mock:marshalResult"/> </route> In the Java DSL, this same route is expressed as: from("direct:marshal") .marshal().json() .to("mock:marshalResult");   How it works... Using Camel JSON simplifies translating your data between JSON and Java. This is convenient when you are dealing with REST endpoints and need Java processors in Camel to do custom message processing later on in the route. Camel JSON provides a wrapper around the JSON libraries for instantiating the Java binding for the JSON data, eliminating more boilerplate code from your integration flows. There's more... Camel JSON works with the XStream library by default, and can be configured to use other JSON libraries, such as Jackson or GSon. These other libraries provide additional features, more customization, and more flexibility that can be leveraged by Camel. To use them, include their respective Camel components, for example, camel-jackson, and specify the library within the json element: <dataFormats> <json id="myJson" library="Jackson"/> </dataFormats>   See also Camel JSON: http://camel.apache.org/json.html Available Data Formats: http://camel.apache.org/data-format.html   Transforming from XML to JSON Camel provides an XML JSON Component that converts your data back and forth between XML and JSON in a single step, without an intermediate Java object representation. It provides a Camel Data Format that allows you to marshal (XML to JSON), or unmarshal (JSON to XML) your data. This recipe will show you how to use the XML JSON Component to convert from XML to JSON, and back. Getting ready Java code for this recipe is located in the org.camelcookbook.transformation.xmljson package. Spring XML files are located under src/main/resources/META-INF/spring and prefixed with xmljson. To use Camel's XML JSON Component, you need to add a dependency element for the camel-xmljson library, which provides an implementation for the XML JSON Data Format. Add the following to the dependencies section of your Maven POM: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-xmljson</artifactId> <version>${camel-version}</version> </dependency>   How to do it... Reference the xmljson Data Format within your route, choosing the marshal(XML to JSON), or unmarshal(JSON to XML) statement, as appropriate: In the XML DSL, this is written as follows: <route> <from uri="direct:marshal"/> <marshal> <xmljson/> </marshal> <to uri="mock:marshalResult"/> </route> In the Java DSL, this same route is expressed as: from("direct:marshal") .marshal().xmljson() .to("mock:marshalResult");   How it works... Using the Camel XML JSON Component simplifies translating your data between XML and JSON, making it convenient to use when you are dealing with REST endpoints. The XML JSON Data Format wraps around the Json-lib library, which provides the core translation capabilities, eliminating more boilerplate code from your integration flows. There's more... You may need to configure XML JSON if you want to fine-tune the output of your transformation. For example, consider the following JSON: [{"@category":"PROGRAMMING","title":{"@lang":"en","#text": "Apache Camel Developer's Cookbook"},"author":[ "Scott Cranton","Jakub Korab"],"year":"2013","price":"49.99"}] This will be converted as follows, by default, which may not be exactly what you want (notice the <a> and <e> elements): <?xml version="1.0" encoding="UTF-8"?> <a> <e category="PROGRAMMING"> <author> <e>Scott Cranton</e> <e>Jakub Korab</e> </author> <price>49.99</price> <title lang="en">Apache Camel Developer's Cookbook</title> <year>2013</year> </e> </a> To configure XML JSON to use <bookstore> as the root element instead of <a>, use <book> for the individual elements instead of <e>, and expand the multiple author values to use a sequence of <author> elements, you would need to tune the configuration of the Data Format before referencing it in your route. In the XML DSL, the definition of the Data Format and the route that uses it is written as follows: <dataFormats> <xmljson id="myXmlJson" rootName="bookstore" elementName="book" expandableProperties="author author"/> </dataFormats> <route> <from uri="direct:unmarshalBookstore"/> <unmarshal ref="myXmlJson"/> <to uri="mock:unmarshalResult"/> </route> In the Java DSL, the same thing is expressed as: XmlJsonDataFormat xmlJsonFormat = new XmlJsonDataFormat(); xmlJsonFormat.setRootName("bookstore"); xmlJsonFormat.setElementName("book"); xmlJsonFormat.setExpandableProperties( Arrays.asList("author", "author")); from("direct:unmarshalBookstore") .unmarshal(xmlJsonFormat) .to("mock:unmarshalBookstoreResult"); This will result in the previous JSON being unmarshalled as follows: <?xml version="1.0" encoding="UTF-8"?> <bookstore> <book category="PROGRAMMING"> <author>Scott Cranton</author> <author>Jakub Korab</author><price>49.99</price> <title lang="en">Apache Camel Developer's Cookbook</title> <year>2013</year> </book> </bookstore>   See also Camel XML JSON: http://camel.apache.org/xmljson.html Available Data Formats: http://camel.apache.org/data-format.html Json-lib: http://json-lib.sourceforge.net   Summary We saw how Apache Camel is flexible in allowing us to transform and convert messages in various formats. This makes Apache Camel an ideal choice for integrating different systems together. Resources for Article: Further resources on this subject: Drools Integration Modules: Spring Framework and Apache Camel [Article] Installing Apache Karaf [Article] Working with AMQP [Article]
Read more
  • 0
  • 0
  • 9453

article-image-panda3d-game-development-scene-effects-and-shaders
Packt
20 Apr 2011
8 min read
Save for later

Panda3D game development: scene effects and shaders

Packt
20 Apr 2011
8 min read
While brilliant gameplay is the key to a fun and successful game, it is essential to deliver beautiful visuals to provide a pleasing experience and immerse the player in the game world. The looks of many modern productions are massively dominated by all sorts of visual magic to create the jaw-dropping visual density that is soaked up by players with joy and makes them feel connected to the action and the gameplay they are experiencing. The appearance of your game matters a lot to its reception by players. Therefore it is important to know how to leverage your technology to get the best possible looks out of it. This is why this article will show you how Panda3D allows you to create great looking games using lights, shaders, and particles. Adding lights and shadows in Panda3d Lights and shadows are very important techniques for producing a great presentation. Proper scene lighting sets the mood and also adds depth to an otherwise flat-looking scene, while shadows add more realism, and more importantly, root the shadow-casting objects to the ground, destroying the impression of models floating in mid-air. This recipe will show you how to add lights to your game scenes and make objects cast shadows to boost your visuals. Getting ready You need to create the setup presented in Setting up the game structure before proceeding, as this recipe continues and builds upon this base code. How to do it... This recipe consists of these tasks: Add the following code to Application.py: from direct.showbase.ShowBase import ShowBase from direct.actor.Actor import Actor from panda3d.core import * class Application(ShowBase): def __init__(self): ShowBase.__init__(self) self.panda = Actor("panda", {"walk": "panda-walk"}) self.panda.reparentTo(render) self.panda.loop("walk") cm = CardMaker("plane") cm.setFrame(-10, 10, -10, 10) plane = render.attachNewNode(cm.generate()) plane.setP(270) self.cam.setPos(0, -40, 6) ambLight = AmbientLight("ambient") ambLight.setColor(Vec4(0.2, 0.1, 0.1, 1.0)) ambNode = render.attachNewNode(ambLight) render.setLight(ambNode) dirLight = DirectionalLight("directional") dirLight.setColor(Vec4(0.1, 0.4, 0.1, 1.0)) dirNode = render.attachNewNode(dirLight) dirNode.setHpr(60, 0, 90) render.setLight(dirNode) pntLight = PointLight("point") pntLight.setColor(Vec4(0.8, 0.8, 0.8, 1.0)) pntNode = render.attachNewNode(pntLight) pntNode.setPos(0, 0, 15) self.panda.setLight(pntNode) sptLight = Spotlight("spot") sptLens = PerspectiveLens() sptLight.setLens(sptLens) sptLight.setColor(Vec4(1.0, 0.0, 0.0, 1.0)) sptLight.setShadowCaster(True) sptNode = render.attachNewNode(sptLight) sptNode.setPos(-10, -10, 20) sptNode.lookAt(self.panda) render.setLight(sptNode) render.setShaderAuto() Start the program with the F6 key. You will see the following scene: How it works... As we can see when starting our program, the panda is lit by multiple lights, casting shadows onto itself and the ground plane. Let's see how we achieved this effect. After setting up the scene containing our panda and a ground plane, one of each possible light type is added to the scene. The general pattern we follow is to create new light instances before adding them to the scene using the attachNewNode() method. Finally, the light is turned on with setLight(), which causes the calling object and all of its children in the scene graph to receive light. We use this to make the point light only affect the panda but not the ground plane. Shadows are very simple to enable and disable by using the setShadowCaster() method, as we can see in the code that initializes the spotlight. The line render.setShaderAuto() enables the shader generator, which causes the lighting to be calculated pixel perfect. Additionally, for using shadows, the shader generator needs to be enabled. If this line is removed, lighting will look coarser and no shadows will be visible at all. Watch the amount of lights you are adding to your scene! Every light that contributes to the scene adds additional computation cost, which will hit you if you intend to use hundreds of lights in a scene! Always try to detect the nearest lights in the level to use for lighting and disable the rest to save performance. There's more... In the sample code, we add several types of lights with different properties, which may need some further explanation. Ambient light sets the base tone of a scene. It has no position or direction—the light color is just added to all surface colors in the scene, which avoids unlit parts of the scene to appear completely black. You shouldn't set the ambient color to very high intensities. This will decrease the effect of other lights and make the scene appear flat and washed out. Directional lights do not have a position, as only their orientation counts. This light type is generally used to simulate sunlight—it comes from a general direction and affects all light-receiving objects equally. A point light illuminates the scene from a point of origin from which light spreads towards all directions. You can think of it as a (very abstract) light bulb. Spotlights, just like the headlights of a car or a flashlight, create a cone of light that originates from a given position and points towards a direction. The way the light spreads is determined by a lens, just like the viewing frustum of a camera. Using light ramps The lighting system of Panda3D allows you to pull off some additional tricks to create some dramatic effects with scene lights. In this recipe, you will learn how to use light ramps to modify the lights affect on the models and actors in your game scenes. Getting ready In this recipe we will extend the code created in Adding lights and shadows found in this article. Please review this recipe before proceeding if you haven't done so yet. How to do it... Light ramps can be used like this: Open Application.py and add and modify the existing code as shown: from direct.showbase.ShowBase import ShowBase from direct.actor.Actor import Actor from panda3d.core import * from direct.interval.IntervalGlobal import * class Application(ShowBase): def __init__(self): ShowBase.__init__(self) self.panda = Actor("panda", {"walk": "panda-walk"}) self.panda.reparentTo(render) self.panda.loop("walk") cm = CardMaker("plane") cm.setFrame(-10, 10, -10, 10) plane = render.attachNewNode(cm.generate()) plane.setP(270) self.cam.setPos(0, -40, 6) ambLight = AmbientLight("ambient") ambLight.setColor(Vec4(0.3, 0.2, 0.2, 1.0)) ambNode = render.attachNewNode(ambLight) render.setLight(ambNode) dirLight = DirectionalLight("directional") dirLight.setColor(Vec4(0.3, 0.9, 0.3, 1.0)) dirNode = render.attachNewNode(dirLight) dirNode.setHpr(60, 0, 90) render.setLight(dirNode) pntLight = PointLight("point") pntLight.setColor(Vec4(3.9, 3.9, 3.8, 1.0)) pntNode = render.attachNewNode(pntLight) pntNode.setPos(0, 0, 15) self.panda.setLight(pntNode) sptLight = Spotlight("spot") sptLens = PerspectiveLens() sptLight.setLens(sptLens) sptLight.setColor(Vec4(1.0, 0.4, 0.4, 1.0)) sptLight.setShadowCaster(True) sptNode = render.attachNewNode(sptLight) sptNode.setPos(-10, -10, 20) sptNode.lookAt(self.panda) render.setLight(sptNode) render.setShaderAuto() self.activeRamp = 0 toggle = Func(self.toggleRamp) switcher = Sequence(toggle, Wait(3)) switcher.loop() def toggleRamp(self): if self.activeRamp == 0: render.setAttrib(LightRampAttrib.makeDefault()) elif self.activeRamp == 1: render.setAttrib(LightRampAttrib.makeHdr0()) elif self.activeRamp == 2: render.setAttrib(LightRampAttrib.makeHdr1()) elif self.activeRamp == 3: render.setAttrib(LightRampAttrib.makeHdr2()) elif self.activeRamp == 4: render.setAttrib(LightRampAttrib. makeSingleThreshold(0.1, 0.3)) elif self.activeRamp == 5: render.setAttrib(LightRampAttrib. makeDoubleThreshold(0, 0.1, 0.3, 0.8)) self.activeRamp += 1 if self.activeRamp > 5: self.activeRamp = 0 Press F6 to start the sample and see it switch through the available light ramps as shown in this screenshot: How it works... The original lighting equation that is used by Panda3D to calculate the final screen color of a lit pixel limits color intensities to values within a range from zero to one. By using light ramps we are able to go beyond these limits or even define our own ones to create dramatic effects just like the ones we can see in the sample program. In the sample code, we increase the lighting intensity and add a method that switches between the available light ramps, beginning with LightRampAttrib.makeDefault() which sets the default clamping thresholds for the lighting calculations. Then, the high dynamic range ramps are enabled one after another. These light ramps allow you to have a higher range of color intensities that go beyond the standard range between zero and one. These high intensities are then mapped back into the displayable range, allocating different amounts of values within it to displaying brightness. By using makeHdr0(), we allocate a quarter of the displayable range to brightness values that are greater than one. With makeHdr1() it is a third and with makeHdr2() we are causing Panda3D to use half of the color range for overly bright values. This doesn't come without any side effects, though. By increasing the range used for high intensities, we are decreasing the range of color intensities available for displaying colors that are within the limits of 0 and 1, thus losing contrast and making the scene look grey and washed out. Finally, with the makeSingleThreshold() and makeDoubleThreshold() methods, we are able to create very interesting lighting effects. With a single threshold, lighting values below the given limit will be ignored, while anything that exceeds the threshold will be set to the intensity given in the second parameter of the method. The double threshold system works analogous to the single threshold, but lighting intensity will be normalized to two possible values, depending on which of the two thresholds was exceeded.
Read more
  • 0
  • 0
  • 9439

article-image-code-real-world
Packt
02 Sep 2015
22 min read
Save for later

From Code to the Real World

Packt
02 Sep 2015
22 min read
 In this article by Jorge R. Castro, author of Building a Home Security System with Arduino, you will learn to read a technical specification sheet, the ports on the Uno and how they work, the necessary elements for a proof of concept. Finally, we will extend the capabilities of our script in Python and rely on NFC technology. We will cover the following points: ProtoBoards and wiring Signals (digital and analog) Ports Datasheets (For more resources related to this topic, see here.) ProtoBoards and wiring There are many ways of working on and testing electrical components, one of the ways developers use is using ProtoBoards (also known as breadboards). Breadboards help eliminate the need to use soldering while testing out components and prototype circuit schematics, it lets us reuse components, enables rapid development, and allows us to correct mistakes and even improve the circuit design. It is a rectangle case composed of internally interconnected rows and columns; it is possible to couple several together. The holes on the face of the board are designed to in way that you can insert the pins of components to mount it. ProtoBoards may be the intermediate step before making our final PCB design, helping eliminate errors and reduce the associated cost. For more information visit http://en.wikipedia.org/wiki/Breadboard. We know have to know more about the wrong wiring techniques when using a breadboard. There are rules that have always been respected, and if not followed, it might lead to shorting out elements that can irreversibly damage our circuit.   A ProtoBoard and an Arduino Uno The ProtoBoard is shown in the preceding image; we can see there are mainly two areas - the vertical columns (lines that begin with the + and - polarity sign), and the central rows (with a coordinate system of letters and numbers). Both + and - usually connect to the electrical supply of our circuit and to the ground. It is advised not to connect components directly in the vertical columns, instead to use a wire to connect to the central rows of the breadboard. The central row number corresponds to a unique track. If we connected one of the leads of a resistor in the first pin of the first row then other lead should be connected to any other pin in another row, and not in the same row. There is an imaginary axis that divides the breadboard vertically in symmetrical halves, which implies that they are electrically independent. We will use this feature to use certain Integrated Circuits (IC), and they will be mounted astride the division.   Protoboard image obtained using Fritzing. Carefully note that in the preceding picture, the top half of the breadboard shows the components mounted incorrectly, while the lower half shows the components mounted the correct way. A chip is set correctly between the two areas, this usage is common for IC's. Fritzing is a tool that helps us create a quick circuit design of our project. Visit http://fritzing.org/download/ for more details on Fritzing. Analog and digital ports Now that we know about the correct usage of a breadboard, we now have another very important concept - ports. Our board will be composed of various inputs and outputs, the number of which varies with the kind of model we have. But what are ports? The Arduino UNO board has ports on its sides. They are connections that allow it to interact with sensors, actuators, and other devices (even with another Arduino board). The board also has ports that support digital and analog signals. The advantage is that these ports are bidirectional, and the programmers are able to define the behavior of these ports. In the following code, the first part shows that we set the status of the ports that we are going to use. This is the setup function: //CODE void setup(){ // Will run once, and use it to // "prepare" I/0 pins of Arduino pinMode(10, OUTPUT); // put the pin 10 as an output pinMode(11, INPUT); // put the pin 11 as an input } Lets take a look at what the digital and analog ports are on the Arduino UNO. Analog ports Analog signals are signals that continuously vary with time These can be explained as voltages that have continuously varying intermediate values. For example, it may vary from 2V to 3.3V to 3.0V, or 3.333V, which means that the voltages varied progressively with time, and are all different values from each other; the figures between the two values are infinite (theoretical value). This is an interesting property, and that is what we want. For example, if we want to measure the temperature of a room, the temperature measure takes values with decimals, need an analog signal. Otherwise, we will lose data, for example, in decimal values since we are not able to store infinite decimal numbers we perform a mathematical rounding (truncating the number). There is a process called discretization, and it is used to convert analog signals to digital. In reality, in the world of microcontrollers, the difference between two values is not infinite. The Arduino UNO's ports have a range of values between 0 and 1023 to describe an analog input signal. Certain ports, marked as PWM or by a ~, can create output signals that vary between values 0 and 255. Digital ports A digital signal consists of just two values - 0s and 1s. Many electronic devices internally have a range currently established, where voltage values from 3.5 to 5V are considered as a logic 1, and voltages from 0 to 2.5V are considered as a logic 0. To better understand this point, let's see an example of a button that triggers an alarm. The only useful cases for an alarm are when the button is pressed to ring the alarm and when it's not pressed; there are only two states observed. So unlike the case of the temperature sensor, where we can have a range of linear values, here only two values exist. Logically, we use these properties for different purposes. The Arduino IDE has some very illustrative examples. You can load them onto your board to study the concepts of analog and digital signals by navigating to File | Examples | Basic | Blink. Sensors There is a wide range of sensors, and without pretending to be an accurate guide of all possible sensors, we will try to establish some small differences. All physical properties or sets of them has an associated sensor, so we can measure the force (presence of people walking on the floor), movement (physical displacement even in the absence of light), smoke, gas, pictures (yes, the cameras also are sensors) noise (sound recording), antennas (radio waves, WiFi, and NFC), and an incredible list that would need a whole book to explain all its fantastic properties. It is also interesting to note that the sensors can also be specific and concrete; however, they only measure very accurate or nonspecific properties, being able to perceive a set of values but more accurately. If you go to an electronics store or a sales portal buy a humidity sensor (and generally any other electronic item), you will see a sensitive price range. In general, expensive sensors indicate that they are more reliable than their cheaper counterparts, the price also indicates the kinds of conditions that it can work in, and also the duration of operation. Expensive sensors can last more than the cheaper variants. When we started looking for a component, we looked to the datasheets of a particular component (the next point will explain what this document is), you will not be surprised to find two very similar models mentioned in the datasheets. It contains operating characteristics and different prices. Some components are professionally deployed (for instance in the technological and military sectors), while others are designed for general consumer electronics. Here, we will focus on those with average quality and foremost an economic price. We proceed with an example that will serve as a liaison with the following paragraph. To do this, we will use a temperature sensor (TMP-36) and an analog port on the Arduino UNO. The following image shows the circuit schematic:   Our design - designed using Fritzing The following is the code for the preceding circuit schematic: //CODE //########################### //Author : Jorge Reyes Castro //Arduino Home Security Book //########################### // A3 <- Input // Sensor TMP36 //########################### //Global Variable int outPut = 0; float outPutToVol = 0.0; float volToTemp = 0.0; void setup(){ Serial.begin(9600); // Start the SerialPort 9600 bauds } void loop(){ outPut = analogRead(A3); // Take the value from the A3 incoming port outPutToVol = 5.0 *(outPut/1024.0); // This is calculated with the values volToTemp = 100.0 *(outPutToVol - 0.5); // obtained from the datasheet Serial.print("_____________________n"); mprint("Output of the sensor ->", outPut); mprint("Conversion to voltage ->", outPutToVol); mprint("Conversion to temperature ->", volToTemp); delay(1000); // Wait 1 Sec. } // Create our print function // smarter than repeat the code and it will be reusable void mprint(char* text, double value){ // receives a pointer to the text and a numeric value of type double Serial.print(text); Serial.print("t"); // tabulation Serial.print(value); Serial.print("n"); // new line } Now, open a serial port from the IDE or just execute the previous Python script. We can see the output from the Arduino. Enter the following command to run the code as python script: $ python SerialPython.py The output will look like this: ____________________ Output of the sensor 145.00 Conversion to voltage 0.71 Conversion to temperature 20.80 _____________________ By using Python script, which is not simple, we managed to extract some data from a sensor after the signal is processed by the Arduino UNO. It is then extracted and read by the serial interface (script in Python) from the Arduino UNO. At this point, we will be able to do what we want with the retrieved data, we can store them in a database, represent them in a function, create a HTML document, and more. As you may have noticed we make a mathematical calculation. However, from where do we get this data? The answer is in the data sheet. Component datasheets Whenever we need to work with or handle an electrical component, we have to study their properties. For this, there are official documents, of variable length, in which the manufacturer carefully describes the characteristics of that component. First of all, we, have to identify that a component can either use the unique ID or model name that it was given when it was manufactured. TMP 36GZ We have very carefully studied the component surface and thus extracted the model. Then, using an Internet browser, we can quickly find the datasheet. Go to http://www.google.com and search for: TMP36GZ + datasheet, or visit http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Temp/TMP35_36_37.pdf to get the datasheet. Once you have the datasheet, you can see that it has various components which look similar, but with very different presentations (this can be crucial for a project, as an error in the choice of encapsulated (coating/presentation) can lead to a bitter surprise). Just as an example, if we confuse the presentation of our circuit, we might end up buying components used in cellphones, and those can hardly be soldered by a standard user as they smaller than your pinkie fingernail). Therefore, an important property to which you must pay attention is the coating/presentation of the components. In the initial pages of the datasheet you see that it shows you the physical aspects of the component. It then show you the technical characteristics, such as the working current, the output voltage, and other characteristics which we must study carefully in order to know whether they will be consistent with our setup. In this case, we are working with a range of input voltage (V) of between 2.7 V to 5.5 V is perfect. Our Arduino has an output of 5V. Furthermore, the temperature range seems appropriate. We do not wish to measure anything below 0V and 5V. Let's study the optimal behavior of the components in temperature ranges in more detail. The behavior of the components is stable only between the desired ranges. This is a very important aspect because although the measurement can be done at the ends supported by the sensor, the error will be much higher and enormously increases the deviation to small variations in ambient temperature. Therefore, always choose or build a circuit with components having the best performance as shown in the optimal region of the graph of the datasheet. Also, always respect and observe that the input voltages do not exceed the specified limit, otherwise it will be irreversibly damaged. To know more about ADC visit http://en.wikipedia.org/wiki/Analog-to-digital_converter. Once we have the temperature sensor, we have to extract the data you need. Therefore, we make a simple calculation supported in the datasheet. As we can see, we feed 5V to the sensor, and it return values between 0 and 1023. So, we use a simple formula that allows us to convert the values obtained in voltage (analog value): Voltage = (Value from the sensor) x (5/1024) The value 1024 is correct, as we have said that the data can range from 0 (including zero as a value) to 1023. This data can be strange to some, but in the world of computer and electronics, zero is seen as a very important value. Therefore, be careful when making calculations. Once we obtain a value in volts, we proceed to convert this measurement in a data in degrees. For this, by using the formula from the datasheet, we can perform the conversion quickly. We use a variable that can store data with decimal point (double or float), otherwise we will be truncating the result and losing valuable information (this may seem strange, but this bug very common). The formula for conversion is Cº = (Voltage -0.5) x 100.0. We now have all the data we need and there is a better implementation of this sensor, in which we can eliminate noise and disturbance from the data. You can dive deeper into these issues if desired. With the preceding explanation, it will not be difficult to achieve. Near Field Communication Near Field Communication (NFC) technology is based on the RFID technology. Basically, the principle consists of two devices fused onto one board, one acting as an antenna to transmit signals and the other that acts as a reader/reciever. It exchanges information using electromagnetic fields. They deal with small pieces of information. It is enough for us to make this extraordinary property almost magical. For more information on RFID and NFC, visit the following links: http://en.wikipedia.org/wiki/Near_field_communication http://en.wikipedia.org/wiki/Radio-frequency_identification Today, we find this technology in identification and access cards (a pioneering example is the Document ID used in countries like Spain), tickets for public transport, credit cards, and even mobile phones (with ability to make payment via NFC). For this project, we will use a popular module PN532 Adafruit RFID/NFC board. Feel free to use any module that suits your needs. I selected this for its value, price, and above all, for its chip. The popular PN532 is largely supported by the community, and there are vast number of publications, tools, and libraries that allow us to integrate it in many projects. For instance, you can use it in conjunction with an Arduino a Raspberry Pi, or directly with your computer (via a USB to serial adapter). Also, the PN532 board comes with a free Mifare 1k card, which we can use for our project. You can also buy tag cards or even key rings that house a small circuit inside, on which information is stored, even encrypted information. One of the benefits, besides the low price of a set of labels, is that we can block access to certain areas of information or even all the information. This allows us in maintaining our valuable data safely or avoid the cloned/duplicate of this security tag. There are a number of standards that allow us to classify the different types of existing cards, one of which is the Mifare 1K card (You can use the example presented here and make small changes to adapt it to other NFC cards). For more information on MIFARE cards, visit http://en.wikipedia.org/wiki/MIFARE. As the name suggests, this model can store up to 1KB (Kilobyte) information, and is of the EEPROM type (can be rewritten). Furthermore, it possesses a serial number unique to each card (this is very interesting because it is a perfect fingerprint that will allow us to distinguish between two cards with the same information). Internally, it is divided into 16 sectors (0-15), and is subdivided into 4 blocks (0-3) with at least 16 bytes of information. For each block, we can set a password that prevents reading your content if it does not pose. (At this point, we are not going to manipulate the key because the user can accidentally, encrypt a card, leaving it unusable). By default, all cards usually come with a default password (ffffffffffff). The reader should consult the link http://www.adafruit.com/product/789, to continue with the examples, or if you select another antenna, search the internet for the same features. The link also has tutorials to make the board compatible with other devices (Raspberry Pi), the datasheet, and the library can be downloaded from Github to use this module. We will have a look at this last point more closely later; just download the libraries for now and follow my steps. It is one of the best advantages of open hardware, that the designs can be changed and improved by anyone. Remember, when handling electrical components, we have to be careful and avoid electrostatic sources. As you have already seen, the module is inserted directly on the Arduino. If soldered pins do not engage directly above then you have to use Dupont male-female connectors to be accessible other unused ports. Once we have the mounted module, we will use the library that is used to control this device (top link) and install it. It is very important that you rename the library to download, eliminate possible blanks or the like. However, the import process may throw an error. Once we have this ready and have our Mifare 1k card close, let's look at a small example that will help us to better understand all this technology and get the UID (Unique Identifier) of our tag: // ########################### // Author : Jorge Reyes Castro // Arduino Home Security Book // ########################### #include <Wire.h> #include <Adafruit_NFCShield_I2C.h> // This is the Adafruit Library //MACROS #define IRQ (2) #define RESET (3) Adafruit_NFCShield_I2C nfc(IRQ, RESET); //Prepare NFC MODULE //SETUP void setup(void){ Serial.begin(115200); //Open Serial Port Serial.print("###### Serial Port Ready ######n"); nfc.begin(); //Start NFC nfc.SAMConfig(); if(!Serial){ //If the serial port don´ work wait delay(500); } } //LOOP void loop(void) { uint8_t success; uint8_t uid[] = { 0, 0, 0, 0}; //Buffer to save the read value //uint8_t ok[] = { X, X, X, X }; //Put your serial Number. * 1 uint8_t uidLength; success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); // READ // If TAG PRESENT if (success) { Serial.println("Found cardn"); Serial.print(" UID Value: t"); nfc.PrintHex(uid, uidLength); //Convert Bytes to Hex. int n = 0; Serial.print("Your Serial Number: t"); // This function show the real value // 4 position runs extracting data while (n < 4){ // Copy and remenber to use in the next example * 1 Serial.print(uid[n]); Serial.print("t"); n++; } Serial.println(""); } delay(1500); //wait 1'5 sec } Now open a serial port from the IDE or just execute the previous Python script. We can see the output from the Arduino. Enter the following command to run the Python code: $ python SerialPython.py The output will look like this: ###### Serial Port Ready ###### Found card UID Value: 0xED 0x05 0xED 0x9A Your Serial Number: 237 5 237 154 So we have our own identification number, but what are those letters that appear above our number? Well, it is hexadecimal, another widely used way to represent numbers and information in the computer. It represents a small set of characters and more numbers in decimal notation than we usually use. (Remember our card with little space. We use hexadecimal to be more useful to save memory). An example is the number 15, we need two characters in tenth, while in decimal just one character is needed f (0xf, this is how the hexadecimal code, preceded by 0x, this is a thing to remember as this would be of great help later on). Open a console and the Python screen. Run the following code to obtain hexadecimal numbers, and will see transformation to decimal (you can replace them with the values previously put in the code): For more information about numbering systems, see http://en.wikipedia.org/wiki/Hexadecimal. $ python >>> 0xED 237 >>> 0x05 5 >>> 0x9A 154 You can see that they are same numbers.   RFID/NFC module and tag Once we are already familiar with the use of this technology, we proceed to increase the difficultly and create our little access control. Be sure to record the serial number of your access card (in decimal). We will make this little montage focus on the use of NFC cards, no authentication key. As mentioned earlier, there is a variant of this exercise and I suggest that the reader complete this on their part, thus increasing the robustness of our assembly. In addition, we add a LED and buzzer to help us improve the usability. Access control The objective is simple: we just have to let people in who have a specific card with a specific serial number. If you want to use encrypted keys, you can change the ID of an encrypted message inside the card with a key known only to the creator of the card. When a successful identification occurs, a green flash lead us to report that someone has had authorized access to the system. In addition, the user is notified of the access through a pleasant sound, for example, will invite you to push the door to open it. Otherwise, an alarm is sounded repeatedly, alerting us of the offense and activating an alert command center (a red flash that is repeated and consistent, which captures the attention of the watchman.) Feel free to add more elements. The diagram shall be as follows:   Our scheme – Image obtained using Fritzing The following is a much clearer representation of the preceding wiring diagram as it avoids the part of the antenna for easy reading:   Our design - Image obtained using Fritzing Once we clear the way to take our design, you can begin to connect all elements and then create our code for the project. The following is the code for the NFC access: //########################### //Author : Jorge Reyes Castro //Arduino Home Security Book //########################### #include <Wire.h> #include <Adafruit_NFCShield_I2C.h> // this is the Adafruit Library //MACROS #define IRQ (2) #define RESET (3) Adafruit_NFCShield_I2C nfc(IRQ, RESET); //Prepare NFC MODULE void setup(void) { pinMode(5, OUTPUT); // PIEZO pinMode(9, OUTPUT); // LED RED pinMode(10, OUTPUT); // LED GREEN okHAL(); Serial.begin(115200); //Open Serial Port Serial.print("###### Serial Port Ready ######n"); nfc.begin(); //Start NFC nfc.SAMConfig(); if(!Serial){ // If the Serial Port don't work wait delay(500); } } void loop(void) { uint8_t success; uint8_t uid[] = { 0, 0, 0, 0}; //Buffer to storage the ID from the read tag uint8_t ok[] = { 237, 5, 237, 154}; //Put your serial Number. uint8_t uidLength; success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); //READ if (success) { okHAL(); // Sound "OK" Serial.println("Found cardn"); Serial.print(" UID Value: t"); nfc.PrintHex(uid, uidLength); // The Value from the UID in HEX int n = 0; Serial.print("Your Serial Number: t"); // The Value from the UID in DEC while (n < 4){ Serial.print(uid[n]); Serial.print("t"); n++; } Serial.println(""); Serial.println(" Wait..n"); // Verification int m = 0, l = 0; while (m < 5){ if(uid[m] == ok[l]){ // Compare the elements one by one from the obtained UID card that was stored previously by us. } else if(m == 4){ Serial.println("###### Authorized ######n"); // ALL OK authOk(); okHAL(); } else{ Serial.println("###### Unauthorized ######n"); // NOT EQUALS ALARM !!! authError(); errorHAL(); m = 6; } m++; l++; } } delay(1500); } //create a function that allows us to quickly create sounds // alarm ( "time to wait" in ms, "tone/power") void alarm(unsigned char wait, unsigned char power ){ analogWrite(5, power); delay(wait); analogWrite(5, 0); } // HAL OK void okHAL(){ alarm(200, 250); alarm(100, 50); alarm(300, 250); } // HAL ERROR void errorHAL(){ int n = 0 ; while(n< 3){ alarm(200, 50); alarm(100, 250); alarm(300, 50); n++; } } // These functions activated led when we called. // (Look at the code of the upper part where they are used) // RED - FAST void authError(){ int n = 0 ; while(n< 20){ digitalWrite(9, HIGH); delay(500); digitalWrite(9, LOW); delay(500); n++; } } // GREEN - SLOW void authOk(){ int n = 0 ; while(n< 5){ digitalWrite(10, HIGH); delay(2000); digitalWrite(10, LOW); delay(500); n++; } } // This code can be reduced to increase efficiency and speed of execution, // but has been created with didactic purposes and therefore increased readability Once you have the copy, compile it, and throw it on your board. Ensure that our creation now has a voice, whenever we start communicating or when someone tries to authenticate. In addition, we have added two simple LEDs that give us much information about our design. Finally, we have our whole system, perhaps it will be time to improve our Python script and try the serial port settings, creating a red window or alarm sound on the computer that is receiving the data. It is the turn of reader to assimilate all of the concepts seen in this day and modify them to delve deeper and deeper into the wonderful world of programming. Summary This has been an intense article, full of new elements. We learned to handle technical documentation fluently, covered the different type of signals and their main differences, found the perfect component for our needs, and finally applied it to a real project, without forgetting the NFC. This has just been introduced, laying the foundation for the reader to be able to modify and study it deeper it in the future. Resources for Article: Further resources on this subject: Getting Started with Arduino[article] Arduino Development[article] The Arduino Mobile Robot [article]
Read more
  • 0
  • 0
  • 9439
article-image-how-to-build-a-remote-control-car-with-zigbee
Bill Pretty
18 Aug 2015
7 min read
Save for later

How to Build a Remote Control Car with Zigbee

Bill Pretty
18 Aug 2015
7 min read
In this first of several articles Bill Pretty, author of Getting Started with Electronic Projects and Building a Home Security System with BeagleBone, shows us how to use a Zigbee point-to-point network to create our very own remote controlled RC car! What Network are we using? In the final chapter of Getting Started with Electronics Projects, I introduced you to the concept of ZigBee RF transmitters and receivers. We used the Type 1 version of XBee devices, because they were capable of “pin mirroring”. In simple terms, this means that whatever change occurs on the I/O pin of the transmitting device is reflected on the corresponding output pin of the receiving XBee device. This feature allows us to use the receiver XBees in a stand-alone configuration, like we did with the alarm system. The type 1 XBee network is configured as a “Star” network. That means that there is only one ‘master’ and in our case, only one end device. Figure 1 Star Network In the figure above, the controlling XBee is shown in red, while the end device(s) are shown in green. The RC cars that we are going to be using in this article have three ‘basic’ types of steering control. I will refer to them as ‘toy’ cars to differentiate them from higher end ‘model’ cars which tend to come out of the box with servo control and microprocessor control. We will be using toy cars that I got from the local thrift store for less than ten dollars, because the remote control was missing! While the remote would come in handy, it isn’t really necessary, because we will be replacing both ends of the system. The first kind of steering system is the simplest and the cheapest to manufacture. A command from the controller tells the front wheels to turn left or right and the wheels will continue to try and turn in the proper direction as long as they are receiving the command, even though the steering motor has hit the limit of the travel. This type of steering may have a series resistor to prevent the motor from burning out, or it may just rely on the limited current capacity of the battery. When the user centres the control, the motor is turned off and an extension spring returns the wheels to the centre position. This makes our control job really easy. We need four signals/commands; forward, reverse, left and right. The spring does the rest. The second type of steering circuit is a simple single pole, double throw switch; which is connected to the motor. The switch changes position when the motor reaches either the full left or full right position. There is no indication of ‘centre’, so this type of steering still relies on a spring for auto-centring. Figure 2 Switch Feedback The third and most complicated type of steering control tends to be seen in toys with rechargeable batteries, like NiCad or NiMH as well. These types of batteries provide more power than alkaline ‘flash light’ batteries. For that reason a slightly more complex steering system is required. This type of system uses an “analog feedback” servo system. What it is is a standard DC motor connected to a potentiometer; so that when the motor turns so does the pot. The wiper of the pot provides a DC voltage that is proportional to the position of the motor. Figure 3 Analog Feedback Servo The steering control circuit will receive three voltages that we are concerned about; full left, full right and centre. This type of servo requires a comparator circuit or a small microprocessor to detect the three positions. More on comparator circuits in future articles. The following circuit will work with the first two types of steering circuits. The circuit diagrams are shown below. Figure 4 In the circuit above, U2 is half of an SN754410 H-Bridge controller integrated circuit. In order for the motor to move the ‘M1’ and ‘M1/’ signals must be at a different level. A logic 0 on M1/ and a logic 1 on M1 will make the motor turn in one direction and a logic 1 on M1/ and a logic 0 on M1 will make it turn in the opposite direction. While either two logic 1’s or 0’s will cause the motor to stop moving. In this way we have either left/right/centre or forward/reverse/stop control. Figure 5 Figure 5 above, shows the connections to the XBee receiver module. As I said earlier, when an I/O pin on the controller goes low, the corresponding pin on the receiver “mirrors” that input. The outputs M1, M1/, M2 and M2/ are connected to the drive and steering motors. The SN754410 is capable of sourcing or sinking about 1 amp, so AUX-1 and AUX-2 can be used to drive LED’s or other devices. The controller circuit is shown below. The circuit is actually taken from a sample circuit I found on the XBee vendor site: http://examples.digi.com/sensors/joystick-with-xbee/ Figure 6 XBee Transmitter The colours represent the wires which come from the joystick. In this case it is a simple arcade style joystick, which uses four micro switches rather than potentiometers. So when the joystick is moved, one or more inputs to the XBee transmitter are grounded (Logic 0) and this information is sent to the receiver in the car. The joystick, available from Adafruit http://examples.digi.com/sensors/joystick-with-xbee/ is shown below. Figure 7 Adafruit Joystick The AUX-1 input is connected to a simple toggle switch, which in this case is used to control the vehicle’s headlights. This is a very simple controller which is designed to control the first two types of vehicles. A more complex design is required to control more complex vehicles. A single board computer such as an Arduino, RaspberryPi or Beaglebone would be required, so that we can read inputs from the joystick as well as digital and analog inputs sent to it from the vehicle. Summary So that’s it for this blog, I hope you enjoyed reading it. In future editions of this topic, I’ll show you how to configure the XBee modules using the Windows application. This method is a lot easier that the one presented in the example on the Digi site. About the Author Bill began his career in electronics in the early 80’s with a small telecom startup company that would eventually become a large multinational. He left there to pursue a career in commercial aviation in Canada’s north. From there he joined the Ontario Center for Microelectronics, a provincially funded research and development center. Bill left there for a career in the military as a civilian contractor at what was then called Defense Research Establishment Ottawa. That began a career which was to span the next 25 years, and continues today. Over the years Bill has acquired extensive knowledge in the field of technical security and started his own company in 2010. That company is called William Pretty Security Inc. and provides support in the form of research and development, to various law enforcement and private security agencies. Bill has published and presented a number of white papers on the subject of technical security. Bill was also a guest presenter for a number of years at the Western Canada Technical Conference, a law enforcement only conference held every year in western Canada. A selection of these papers is available for download from his web site. www.williamprettysecurity.com If you’re interested in building more of your own projects, then be sure to check out Bill’s titles available now in both print and eBook format! If you’re new to working with microcontrollers be sure to pick up Getting Started with Electronic Projects to start creating a whole host of great projects you can do in a single weekend with LM555, ZigBee, and BeagleBone components! If you’re looking for something more advanced to tinker with, then Bill’s other title - Building a Home Security System with BeagleBone – is perfect for hobbyists looking to make a bigger project!
Read more
  • 0
  • 0
  • 9435

article-image-connecting-backend-servers-should-know
Packt
27 May 2013
5 min read
Save for later

Connecting to backend servers (Should know)

Packt
27 May 2013
5 min read
(For more resources related to this topic, see here.) Getting ready If you have a server architecture diagram, that's a good place to start listing all the required servers and grouping them, but you'll also need some technical data about those servers. You may find this information in a server monitoring diagram, where you will find the IP addresses, ports, and luckily a probing URL for health checks. In our case, the main VCL configuration file default.vcl is located at /etc/varnish and defines the configuration that the Varnish Cache will use during the life cycle of the request, including the backend servers list. How to do it... Open the default vcl file by using the following command: # sudo vim /etc/varnish/default.vcl A simple backend declaration would be: backend server01 {.host = "localhost";.port = "8080";} This small block of code indicates the name of the backend (server01), and also the hostname or IP, and which port to connect to. Save the file and reload the configuration using the following command: # sudo service varnish reload At this point, Varnish will proxy every request to the first declared backend using its default VCL file. Give it a try and access a known URL (like the index of your website) through the Varnish Cache and make sure that the content is delivered as it would be without Varnish. For testing purposes, this is an okay backend declaration, but we need to make sure that our backend servers are up and waiting for requests before we really start to direct web traffic to them. Let's include a probing request to our backend: backend website {.host = "localhost";.port = "8080";.probe = {.url = "/favicon.ico";.timeout = 60ms;.interval = 2s;.window = 5;.threshold = 3;}} Varnish will now probe the backend server using the provided URL with a timeout of 60 ms, every couple of seconds. To determine if a backend is healthy, it will analyze the last five probes. If three of them result in 200 – OK, the backend is marked as Healthy and the requests are forwarded to this backend; if not, the backend is marked as Sick and will not receive any incoming requests until it's Healthy again. Probe the backend servers that require additional information: In case your backend server requires extra headers or has an HTTP basic authentication, you can change the probing from URL to Request and specify a raw HTTP request. When using the Request probe, you'll always need to provide a Connection: close header or it will not work. This is shown in the following code snippet: backend api {.host = "localhost";.port = "8080";.probe = {.request ="GET /status HTTP/1.1""Host: www.yourhostname.com""Connection: close""X-API-Key: e4d909c290d0fb1ca068ffaddf22cbd0""Accept: application/json".timeout = 60ms;.interval = 2s;.window = 5;.threshold = 3;}} Choose a backend server based on incoming data: After declaring your backend servers, you can start directing the clients' requests. The most common way to choose which backend server will respond to a request is according to the incoming URL, as shown in the following code snippet: vcl_recv {if ( req.url ~ "/api/") {set req.backend = api;} else {Set req.backend = website;}} Based on the preceding configuration, all requests that contain /api/ (www.yourdomain.com/api/) in the URL will be sent to the backend named api and the others will reach the backend named website. You can also pick the correct backend server, based on User-agent header, Client IP (geo-based), and pretty much every information that comes with the request. How it works... By probing your backend servers, you can automate the removal of a sick backend from your cluster, and by doing so, you avoid delivering a broken page to your customer. As soon as your backend starts to behave normally, Varnish will add it back to the cluster pool. Directing requests to the appropriate backend server is a great way to make sure that every request reaches its destination, and gives you the flexibility to provide content based on the incoming data, such as a mobile device or an API request. There's more... If you have lots of servers to be declared as backend, you can declare probes as a separated configuration block and make reference to that block later at the backend specifications, avoiding repetition and improving the code's readability. probe favicon {.url = "/favicon.ico";.timeout = 60ms;.interval = 2s;.window = 5;.threshold = 3;}probe robots {.url = "/robots.txt";.timeout = 60ms;.interval = 2s;.window = 5;.threshold = 3;}backend server01 {.host = "localhost";.port = "8080";.probe = favicon;}backend server02 {.host = "localhost";.port = "8080";.probe = robots;} The server01 server will use the probe named favicon, and the server02 server will use the probe named robots. Summary This article explained how to connect to backend servers. Resources for Article : Further resources on this subject: Security in Plone Sites [Article] Professional Plone Development: Foreword by Alexander Limi [Article] Microsoft SQL Server 2008 High Availability: Understanding Domains, Users, and Security [Article]
Read more
  • 0
  • 0
  • 9433
Modal Close icon
Modal Close icon